Slide 1

Slide 1 text

(partially) Non-volatile mruby 2019-04-20 RubyKaigi 2019 Yurie Yamane / Masayoshi Takahashiɹ Team Yamanekko

Slide 2

Slide 2 text

Note: This is a technical session using C ‣You need to know about C language basics ‣ constant (const) ‣ structure ‣ pointers and references

Slide 3

Slide 3 text

Understand this session Completely in 10 seconds

Slide 4

Slide 4 text

What do we want to do in 10 sec. While Executing (current) ROM Ruby’s Objects RAM

Slide 5

Slide 5 text

What do we want to do in 10 sec. Before Executing (current) ROM RAM Ruby’s Objects

Slide 6

Slide 6 text

What do we want to do in 10 sec. Before Executing (ours) ROM RAM Ruby’s Objects

Slide 7

Slide 7 text

What do we want to do in 10 sec. While Executing (ours) RAM new Ruby’s Objects ROM Ruby’s Objects

Slide 8

Slide 8 text

Contents ‣ Understand this session completely in 10 seconds ‣ Why ROM and RubyKaigi 2018 wrap up and new our approach ‣ nvgen ‣ Introduction to mruby’s objects in C ‣ Class objects in depth ‣ Fix to work with ROM ‣ Benchmark ‣ Future works

Slide 9

Slide 9 text

About Us

Slide 10

Slide 10 text

Yurie Yamane ‣TOPPERS project ‣ET Robocon

Slide 11

Slide 11 text

Masayoshi Takahashi ‣ Ruby no Kai ‣ RubyKaigi ‣ TechBookFest ‣ AozoraHack

Slide 12

Slide 12 text

Masayoshi Takahashi

Slide 13

Slide 13 text

Today’s Topic

Slide 14

Slide 14 text

memory management in mruby for embedded systems

Slide 15

Slide 15 text

RubyKaigi 2018

Slide 16

Slide 16 text

https://www.slideshare.net/yamanekko/mruby-can-be-more- lightweight-102604291

Slide 17

Slide 17 text

Why and How

Slide 18

Slide 18 text

Why QSJDF 3". 30. NSVCZ -&(0 .JOE4UPSNT  ZFO .# .# 0, (31&"$)  ZFO .# .# 0, .4UBDL  ZFO ,# .# 0, OVDMFP';(  ZFO ,# ,# 0, OVDMFP'3&  ZFO ,# ,# 0, OVDMFP'3&  ZFO ,# ,# "SEVJOPVOP  ZFO ,# ,# /( ref)

Slide 19

Slide 19 text

How A B C reduce RAM use ROM tuning by #define change implementation

Slide 20

Slide 20 text

Why do we want to use ROM more ‣RAM is small and precious ‣ROM is large, but not used well in dynamic language ‣because ROM cannot be modified in execution time

Slide 21

Slide 21 text

Every Objects in Flash ROM???

Slide 22

Slide 22 text

hello world in mruby #include #include int main(void) { mrb_state *mrb = mrb_open(); if (!mrb) { /* handle error */ } mrb_load_string(mrb, "puts 'hello world'"); mrb_close(mrb); return 0; } initialize load & run app.c

Slide 23

Slide 23 text

hello world in mruby #include #include #include “bytecode.h” int main(void) { mrb_state *mrb = mrb_open(); if (!mrb) { /* handle error */ } mrb_load_irep(mrb, code); mrb_close(mrb); return 0; } initialize load & run const uint8_t code[] = { 0x45,0x54,0x49,0x52, 0x30,0x30,0x30,0x35, 0x3b,0x7c,0x00,0x00, 0x00,0x58,0x4d,0x41, 0x54,0x5a,0x30,0x30, 0x30,0x30,0x49,0x52, 0x45,0x50,0x00,0x00, 0x00,0x3a,0x30,0x30, 0x30,0x32,0x00,0x00, 0x00,0x56,0x00,0x01, 0x00,0x04,0x00,0x00, 0x00,0x00,0x00,0x0c, 0x10,0x01,0x4f,0x02, app.c bytecode.h

Slide 24

Slide 24 text

Build apps of mruby Ruby script sample.rb bytecode.h app.c executable mrbc GCC

Slide 25

Slide 25 text

mrb_open() ‣Initialization ≒ mrb_open();

Slide 26

Slide 26 text

Every Objects in initialized stage in Flash ROM?

Slide 27

Slide 27 text

mrb_open() ‣Initialize GC and heap memory ‣initialize Symbols and Strings ‣Initialize Standard Classes in C ‣initialize Standard Classes in Ruby ‣initialize mrbgems in C and/or Ruby

Slide 28

Slide 28 text

mrb_open() ‣Initialize GC and heap memory ‣initialize Symbols and Strings ‣Initialize Standard Classes in C ‣initialize Standard Classes in Ruby ‣initialize mrbgems in C and/or Ruby

Slide 29

Slide 29 text

What’s Difference ‣Previous approach ‣Symbols and method definitions ‣New approach ‣+ Objects and IREPs

Slide 30

Slide 30 text

Previous / New ROM ROM ROM RAM RAM RAM 2018 2019 ROM RAM

Slide 31

Slide 31 text

Our approach (in Ruby) A = Array.new A << 1 if A.size >= 1 A += [2, 3] end A = [1, 2, 3] original generated

Slide 32

Slide 32 text

Our approach (in Ruby) A = Array.new A << 1 if A.size >= 1 A += [2, 3] end A = [1, 2, 3] original generated A : [1, 2, 3] Internal data structure

Slide 33

Slide 33 text

Our approach ‣ build generator with mruby ‣ executing mrb_open() ‣ generate C files using mruby ‣ build new executable (binary) ‣ execute mrb_load_state_allocf()ɹ in runtime *.c mruby mruby app.c runtime generator Executable

Slide 34

Slide 34 text

mrb_load_state_allocf() ‣ mrb_open() ‣ normal VM initializer ‣mrb_open_allocf(mrb_allocf f, void *ud) ‣use custom allocation function f ‣ mrb_load_state_allocf(mrb_state *mrb, mrb_allocf f, void *ud) ‣ use custom allocation function and initialized VM image

Slide 35

Slide 35 text

Using ROM

Slide 36

Slide 36 text

How to put them on ROM ‣ use structures ‣ use const const char nv_string_0[] = "mruby - Copyright (c) …"; const struct RString nv_object_141 = { .tt=MRB_TT_STRING, .color=7, .flags=141, .c=(struct RClass *)&nv_object_186, .gcnext=NULL, .as = { .heap = { .ptr=(char *)&nv_string_0 } } }; generated.c

Slide 37

Slide 37 text

How to put them on ROM generated.c mruby Executable +

Slide 38

Slide 38 text

How to put Symbols on ROM ‣ All Symbols should be defined ‣ to use structures in ROM ‣ Access to Symbols should be fast ‣ → We use gperf (perfect hash Generator)

Slide 39

Slide 39 text

How to put Symbols on ROM ‣ generate *.key file from symbol objects ‣ generate *.c file with gperf presym.key Symbols presym.c

Slide 40

Slide 40 text

How to put them on ROM generated.c mruby Executable + + presym.c

Slide 41

Slide 41 text

nvgen

Slide 42

Slide 42 text

nvgen ‣ Non-Volatile mruby GENerator ‣ generate 2 files ‣generated.c ‣presym.key

Slide 43

Slide 43 text

nvgen ‣ execute mrb_open() ‣ generate Objects, strings, symbols as C structures ‣ dump all symbols into presym.key ‣ dump all structures into generated.c mruby nvgen generated.c presym.c presym.key

Slide 44

Slide 44 text

Can we put them all on ROM? ‣Of course, No ‣Many methods to update pre-defined objects ‣Open classes ‣Object#freeze ‣String#reverse!

Slide 45

Slide 45 text

Introduction to mruby’s Objects in C

Slide 46

Slide 46 text

mruby’s Objects in C ‣mrb_value ‣small objects data represented in 4 bytes ‣ex) Integer, Symbol, true/false/nil ‣struct RBasic* ‣objects data larger than 4 bytes ‣ex) String, Array, Class, user-defined classes

Slide 47

Slide 47 text

mrb_value ‣ Object itself ‣ mrb_vtype: value type ‣ value: i (Integer), sym (Symbol), p (others) ‣ p is pointer to RXXX typedef struct mrb_value { union { void *p; mrb_int i; mrb_sym sym; } value; enum mrb_vtype tt; } mrb_value;

Slide 48

Slide 48 text

struct RBasic ‣ body of Object ‣ color: for GC ‣ flags: attrs of the object ‣ c: class of the object ‣ gcnext: for GC #define MRB_OBJECT_HEADER \ enum mrb_vtype tt:8;\ uint32_t color:3;\ uint32_t flags:21;\ struct RClass *c;\ struct RBasic *gcnext struct RBasic { MRB_OBJECT_HEADER; };

Slide 49

Slide 49 text

other struct RXXXX ‣ RObject is Object class ‣ RClass is Class class ‣ RClass have super class and method tables ‣ Similar to RArray, RHash, and so on struct RObject { MRB_OBJECT_HEADER; struct iv_tbl *iv; }; struct RClass { MRB_OBJECT_HEADER; struct iv_tbl *iv; struct kh_mt *mt; struct RClass *super; };

Slide 50

Slide 50 text

Class objects in depth

Slide 51

Slide 51 text

mruby VM has class objects Proc String Float Fixnum Symbol Kernel Object Class Array Hash TrueClass FalseClass Module Range NilClass mrb_state (mruby VM)

Slide 52

Slide 52 text

class has ivars and methods iv mt internal data methods class object (RClass) iv: instance variable mt: method table

Slide 53

Slide 53 text

Ruby objects are struct in C struct RClass { MRB_OBJECT_HEADER; struct iv_tbl *iv; struct kh_mt *mt; struct RClass *super; };

Slide 54

Slide 54 text

Memory Usage ‣Flash (ROM) ‣Heap (RAM) ‣use with malloc() ‣target of GC ‣Global variables (RAM) ‣use without malloc()

Slide 55

Slide 55 text

Which’s in ROM, Which’s in RAM ‣ROM: Immutable things ‣RAM: Mutable things ‣a member of Immutable structure can be Mutable ‣and vice versa

Slide 56

Slide 56 text

Which’s in ROM, Which’s in RAM class mrb_state iv_tbl internal data methods ROM mt methods HEAP GV

Slide 57

Slide 57 text

Which’s in ROM, Which’s in RAM class mrb_state iv_tbl internal data methods GV ROM mt methods HEAP

Slide 58

Slide 58 text

What’s structures in ROM ‣Objects (RBasic) ‣Symbols ‣Strings ‣IREPs ‣methods defined in initializing time ‣copy of VM (mrb_state)

Slide 59

Slide 59 text

What’s structures in RAM ‣body of Hash ‣body of instance variables ‣methods defined at executing time ‣context ‣instance_vars and methods ‣current VM (mrb_state)

Slide 60

Slide 60 text

Is it work? ‣You’ll get many problems ‣cannot define new classes ‣cannot use mrb_free() ‣cannot do GC ‣cannot use Object#freeze

Slide 61

Slide 61 text

Is it work? ‣You’ll get many problems ‣cannot find (function|variable) names of C from (function|variable) addresses ‣need to generate C code

Slide 62

Slide 62 text

Fix to work with ROM

Slide 63

Slide 63 text

Function Name Resolution mrb_method_t vals = mrb_malloc(mrb, /* ... */); vals[0].func_p = 1; vals[0].func = gc_start; dump_vals(vals); const mrb_method_t nv_mt_vals_1[] = { { .func_p=1, {.func=(mrb_func_t)&gc_start} }, /* ... */ };

Slide 64

Slide 64 text

Function Name Resolution ‣use nm command to save symbol table of nvgen ‣nvgen parses the file and get address of functions ‣This method is used by TOPPERS configurator. $ nm nvgen > nvgen.syms $ ./nvgen nvgen.syms > generated.c

Slide 65

Slide 65 text

String’s pointer to char* ‣String object has a pointer to C string (char*) ‣But String is not mutable ‣To fix this, String used in mruby/mrbgems should be freezed

Slide 66

Slide 66 text

Using TLSF malloc ‣We want to know if a structure is in global variable area or in the heap area ‣Global variable should not be free() ‣Use TLSF malloc instead of standard malloc() ‣With TLSF malloc, we can know the object is in heap or not ‣see github.com/yamanekko/mruby-tlsf for detail

Slide 67

Slide 67 text

GC supporting ROM and RAM ‣ mruby uses tri-color GC (Black, White, Gray) ‣ We use quad-color GC, add Red ‣ Red are never GCed; objects in ROM are Red ‣ At first of GC cycle, all children of Red objects are marked ‣ VM has a list of Red objects

Slide 68

Slide 68 text

support flags in RAM ‣ obj->flags is used as status of objects ‣ flags should be mutable ‣ So an array of flags for ROM’s objects are located in RAM ‣ add macro to read and write them ‣ obj->flags in ROM are indexes of the array

Slide 69

Slide 69 text

Finding methods ‣ method tables are in both ROM and RAM ‣ tables for pre-defined methods are in ROM ‣ using iv_tbl to store pointer of pre-defined method tables ‣ key is __mt2__, which is not used as instance variables

Slide 70

Slide 70 text

Benchmark

Slide 71

Slide 71 text

     EFGBVMU  /7    

Slide 72

Slide 72 text

Future works

Slide 73

Slide 73 text

Future works ‣nvgen as mrbgem ‣feedback to mruby/mruby ‣workshop

Slide 74

Slide 74 text

Special Thanks to: ‣ This work is supported Ruby Association grant program in 2018

Slide 75

Slide 75 text

and Thank you!