mruby can be more
lightweight
2018-06-01 RubyKaigi 2018
Yurie Yamane
Team Yamanekko
About me
• yurie yamane
• Team yamanekko
• GitHub: https://github.com/yamanekko
• Qiita: https://qiita.com/yamanekko
• a member of Toppers project
• a staff of SWEST
(Summer Workshop on Embedded System Technologies)
https://swest.toppers.jp/
TOPAME
matz
About me
• smaller mruby
• low cost microcomputer
• IDE for mruby(VS Code)
• porting nomitory to VS Code
• DEMO
• mruby for ET robot contest
sponsors
wanted!
Today's topic
• how to make mruby smaller
• why?
• how?
Why?
price RAM ROM mruby
LEGO
MindStorms
60,000yen 64MB 16MB OK
GR-PEACH 10,000yen 10MB 8MB OK
nucleo
F412ZG
3,000yen 256KB 1024KB OK
nucleo
F411RE
2,000yen 128KB 512KB OK
Arduino uno 3,000yen 2KB 32KB NG
porting microcomputers
ref)
F411RE or F401RE
F411RE F401RE
RAM:96KB
ROM:512KB
RAM:128KB
ROM:512KB
How?
how to reduce
A
B
C
reduce RAM
use ROM
tuning by #define
change
implementation
RAM size
0
40000
80000
120000
160000
default A B and C
66919
82783
152829
• DEMO
Assigned symbols to ROM
• why method definition in RAM?
RAM
Assigned symbols to ROM
predefined 
method RAM
ROM
predefined 
method
 method
 method
RAM
Assigned symbols to ROM
symbol
symbol
RAM
ROM
predefined 
method
 method
symbol
symbol
predefined 
method
 method
RAM
RAM
ROM
Assigned symbols to ROM
khash
 method
khash
 method
 method
method table
struct RClass {

MRB_OBJECT_HEADER;

struct iv_tbl *iv;

struct kh_mt *mt;

struct RClass *super;

};
RClass
RAM
method table
keys
vals
typedef struct kh_mt{

khint_t n_buckets;

khint_t size;

khint_t n_occupied;

uint8_t *ed_flags;

mrb_sym *keys;

mrb_method_t *vals;

} kh_mt_t;
ed_flags
buckets
https://tatsu-zine.com/books/ruby-under-a-microscope-ja
"Ruby Under a Microscope"
method table
RClass
mt2
struct RClass {

MRB_OBJECT_HEADER;

struct iv_tbl *iv;

struct kh_mt *mt;

#ifdef USE_PRESYM

struct method_table *mt2;

#endif

struct RClass *super;

};
hash vs array
keys
vals
Array
RAM
ROM struct method_table{

  mrb_sym sym;

  mrb_method_t method;

};
typedef struct kh_mt{

khint_t n_buckets;

khint_t size;

khint_t n_occupied;

uint8_t *ed_flags;

mrb_sym *keys;

mrb_method_t *vals;

} kh_mt_t;

ed_flags
buckets
sym
method
Ruby method to C function
• Ex.String class
String class
to_i mrb_str_to_i
upcase mrb_str_upcase
length mrb_str_size
reverse mrb_str_reverse
size mrb_str_size
mrb_define_method(mrb, a, "size",mrb_str_size, MRB_ARGS_NONE());
Ruby method to C function
• perf
method name id
to_i 290
upcase 298
length 212
reverse 259
size 271
id function name
290 mrb_str_to_i
298 mrb_str_upcase
212 mrb_str_size
259 mrb_str_reverse
271 mrb_str_size
extract symbols
• *.c
• intern literal
• method
• const
• global const
• class
• module
• class method
• *.rb
• def
• class
mrb_intern_lit(mrb, "to_a")

mrb_define_class(mrb, "Array", mrb->object_class);

mrb_define_method(mrb, a, "+", mrb_ary_plus, MRB_ARGS_REQ(1));

mrb_define_method(mrb, a, "size",mrb_ary_size, MRB_ARGS_NONE());
class Foo

def foo

(...)

end

end
ROM
mrb_method_search_vm
Dynamically added methods
are defined here
 method
RAM
khash
 method
irep_remove_lv
remove local variable's names
• make bytecode without irep->lv
static void

irep_remove_lv(mrb_state *mrb, mrb_irep *irep)

{

int i;

if (irep->lv) {

mrb_free(mrb, irep->lv);

irep->lv = NULL;

}

for (i = 0; i < irep->rlen; ++i) {

irep_remove_lv(mrb, irep->reps[i]);

}

}
khash size
• KHASH_DEFAULT_SIZE 4
• KHASH_MIN_SIZE
#ifndef KHASH_DEFAULT_SIZE

# define KHASH_DEFAULT_SIZE 32

#endif

#define KHASH_MIN_SIZE 8
# define KHASH_DEFAULT_SIZE 4
#ifndef KHASH_DEFAULT_SIZE

# define KHASH_DEFAULT_SIZE 32

#endif

#define KHASH_MIN_SIZE 4
others
delete -g option
• mrbc.compile_options = "-g -B%{funcname} -o-"
• MRB_USE_ETEXT_EDATA
mrbconf.md
. = ALIGN(4);

_etext = .; /* define a global symbols at end of code
*/

} >FLASH
{

. = ALIGN(4);

_sdata = .; /* create a global symbol at data start */

*(.data) /* .data sections */

*(.data*) /* .data* sections */

. = ALIGN(4);

_edata = .; /* define a global symbol at data end */

} >RAM AT> FLASH
• MRB_HEAP_PAGE_SIZE
• Specifies number of `RBasic` per each heap
page.
• MRB_WORD_BOXING
• If defined represent `mrb_value` as a word.
• If defined `Float` will be a mruby object with
`RBasic`.
• MRB_STR_BUF_MIN_SIZE
• Specifies initial capacity of `RString` created
by `mrb_str_buf_new` function. mrbconf.md
Future works
RClass
mt2 to iv
RClass
struct RClass {

MRB_OBJECT_HEADER;

struct iv_tbl *iv;

struct kh_mt *mt;

#ifdef USE_PRESYM

struct method_table *mt2;

#endif

struct RClass *super;

};
iv
mt2
iv
mt2
• Implementation to unsupported class
• known bug
• "remove_method" can't remove method on
ROM
🙀
Thanks

mruby can be more lightweight

  • 1.
    mruby can bemore lightweight 2018-06-01 RubyKaigi 2018 Yurie Yamane Team Yamanekko
  • 2.
    About me • yurieyamane • Team yamanekko • GitHub: https://github.com/yamanekko • Qiita: https://qiita.com/yamanekko • a member of Toppers project • a staff of SWEST (Summer Workshop on Embedded System Technologies) https://swest.toppers.jp/ TOPAME matz
  • 3.
    About me • smallermruby • low cost microcomputer • IDE for mruby(VS Code) • porting nomitory to VS Code • DEMO • mruby for ET robot contest sponsors wanted!
  • 4.
    Today's topic • howto make mruby smaller • why? • how?
  • 5.
  • 6.
    price RAM ROMmruby LEGO MindStorms 60,000yen 64MB 16MB OK GR-PEACH 10,000yen 10MB 8MB OK nucleo F412ZG 3,000yen 256KB 1024KB OK nucleo F411RE 2,000yen 128KB 512KB OK Arduino uno 3,000yen 2KB 32KB NG porting microcomputers ref)
  • 7.
    F411RE or F401RE F411REF401RE RAM:96KB ROM:512KB RAM:128KB ROM:512KB
  • 8.
  • 9.
    how to reduce A B C reduceRAM use ROM tuning by #define change implementation
  • 10.
  • 11.
  • 12.
  • 13.
    • why methoddefinition in RAM?
  • 14.
    RAM Assigned symbols toROM predefined  method RAM ROM predefined  method  method  method
  • 15.
    RAM Assigned symbols toROM symbol symbol RAM ROM predefined  method  method symbol symbol predefined  method  method
  • 16.
    RAM RAM ROM Assigned symbols toROM khash  method khash  method  method
  • 17.
    method table struct RClass{ MRB_OBJECT_HEADER; struct iv_tbl *iv; struct kh_mt *mt; struct RClass *super; }; RClass
  • 18.
    RAM method table keys vals typedef structkh_mt{ khint_t n_buckets; khint_t size; khint_t n_occupied; uint8_t *ed_flags; mrb_sym *keys; mrb_method_t *vals; } kh_mt_t; ed_flags buckets https://tatsu-zine.com/books/ruby-under-a-microscope-ja "Ruby Under a Microscope"
  • 19.
    method table RClass mt2 struct RClass{ MRB_OBJECT_HEADER; struct iv_tbl *iv; struct kh_mt *mt; #ifdef USE_PRESYM struct method_table *mt2; #endif struct RClass *super; };
  • 20.
    hash vs array keys vals Array RAM ROMstruct method_table{   mrb_sym sym;   mrb_method_t method; }; typedef struct kh_mt{ khint_t n_buckets; khint_t size; khint_t n_occupied; uint8_t *ed_flags; mrb_sym *keys; mrb_method_t *vals; } kh_mt_t; ed_flags buckets sym method
  • 21.
    Ruby method toC function • Ex.String class String class to_i mrb_str_to_i upcase mrb_str_upcase length mrb_str_size reverse mrb_str_reverse size mrb_str_size mrb_define_method(mrb, a, "size",mrb_str_size, MRB_ARGS_NONE());
  • 22.
    Ruby method toC function • perf method name id to_i 290 upcase 298 length 212 reverse 259 size 271 id function name 290 mrb_str_to_i 298 mrb_str_upcase 212 mrb_str_size 259 mrb_str_reverse 271 mrb_str_size
  • 23.
    extract symbols • *.c •intern literal • method • const • global const • class • module • class method • *.rb • def • class mrb_intern_lit(mrb, "to_a") mrb_define_class(mrb, "Array", mrb->object_class); mrb_define_method(mrb, a, "+", mrb_ary_plus, MRB_ARGS_REQ(1)); mrb_define_method(mrb, a, "size",mrb_ary_size, MRB_ARGS_NONE()); class Foo def foo (...) end end
  • 24.
    ROM mrb_method_search_vm Dynamically added methods aredefined here  method RAM khash  method
  • 25.
  • 26.
    remove local variable'snames • make bytecode without irep->lv static void irep_remove_lv(mrb_state *mrb, mrb_irep *irep) { int i; if (irep->lv) { mrb_free(mrb, irep->lv); irep->lv = NULL; } for (i = 0; i < irep->rlen; ++i) { irep_remove_lv(mrb, irep->reps[i]); } }
  • 27.
    khash size • KHASH_DEFAULT_SIZE4 • KHASH_MIN_SIZE #ifndef KHASH_DEFAULT_SIZE # define KHASH_DEFAULT_SIZE 32 #endif #define KHASH_MIN_SIZE 8 # define KHASH_DEFAULT_SIZE 4 #ifndef KHASH_DEFAULT_SIZE # define KHASH_DEFAULT_SIZE 32 #endif #define KHASH_MIN_SIZE 4
  • 28.
  • 29.
    delete -g option •mrbc.compile_options = "-g -B%{funcname} -o-"
  • 30.
    • MRB_USE_ETEXT_EDATA mrbconf.md . =ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH
  • 31.
    • MRB_HEAP_PAGE_SIZE • Specifiesnumber of `RBasic` per each heap page. • MRB_WORD_BOXING • If defined represent `mrb_value` as a word. • If defined `Float` will be a mruby object with `RBasic`. • MRB_STR_BUF_MIN_SIZE • Specifies initial capacity of `RString` created by `mrb_str_buf_new` function. mrbconf.md
  • 32.
  • 33.
    RClass mt2 to iv RClass structRClass { MRB_OBJECT_HEADER; struct iv_tbl *iv; struct kh_mt *mt; #ifdef USE_PRESYM struct method_table *mt2; #endif struct RClass *super; }; iv mt2 iv mt2
  • 34.
    • Implementation tounsupported class • known bug • "remove_method" can't remove method on ROM 🙀
  • 35.