Upgrade to Pro — share decks privately, control downloads, hide ads and more …

(partially) Non-volatile mruby

(partially) Non-volatile mruby

presentation material of "(partially) Non-volatile mruby" in RubyKaigi 2019
https://rubykaigi.org/2019/presentations/yuri_at_earth.html

644ee43c84fe676bbbdb658691b373ac?s=128

Yamanekko

April 20, 2019
Tweet

More Decks by Yamanekko

Other Decks in Programming

Transcript

  1. (partially) Non-volatile mruby 2019-04-20 RubyKaigi 2019 Yurie Yamane / Masayoshi

    Takahashiɹ Team Yamanekko
  2. Note: This is a technical session using C ‣You need

    to know about C language basics ‣ constant (const) ‣ structure ‣ pointers and references
  3. Understand this session Completely in 10 seconds

  4. What do we want to do in 10 sec. While

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

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

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

    Executing (ours) RAM new Ruby’s Objects ROM Ruby’s Objects
  8. 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
  9. About Us

  10. Yurie Yamane ‣TOPPERS project ‣ET Robocon

  11. Masayoshi Takahashi ‣ Ruby no Kai ‣ RubyKaigi ‣ TechBookFest

    ‣ AozoraHack
  12. Masayoshi Takahashi

  13. Today’s Topic

  14. memory management in mruby for embedded systems

  15. RubyKaigi 2018

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

  17. Why and How

  18. 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)
  19. How A B C reduce RAM use ROM tuning by

    #define change implementation
  20. 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
  21. Every Objects in Flash ROM???

  22. hello world in mruby #include <mruby.h> #include <mruby/compile.h> 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
  23. hello world in mruby #include <mruby.h> #include <mruby/compile.h> #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
  24. Build apps of mruby Ruby script sample.rb bytecode.h app.c executable

    mrbc GCC
  25. mrb_open() ‣Initialization ≒ mrb_open();

  26. Every Objects in initialized stage in Flash ROM?

  27. 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
  28. 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
  29. What’s Difference ‣Previous approach ‣Symbols and method definitions ‣New approach

    ‣+ Objects and IREPs
  30. Previous / New ROM ROM ROM RAM RAM RAM 2018

    2019 ROM RAM
  31. Our approach (in Ruby) A = Array.new A << 1

    if A.size >= 1 A += [2, 3] end A = [1, 2, 3] original generated
  32. 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
  33. 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
  34. 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
  35. Using ROM

  36. 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
  37. How to put them on ROM generated.c mruby Executable +

  38. 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)
  39. How to put Symbols on ROM ‣ generate *.key file

    from symbol objects ‣ generate *.c file with gperf presym.key Symbols presym.c
  40. How to put them on ROM generated.c mruby Executable +

    + presym.c
  41. nvgen

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

    ‣presym.key
  43. 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
  44. Can we put them all on ROM? ‣Of course, No

    ‣Many methods to update pre-defined objects ‣Open classes ‣Object#freeze ‣String#reverse!
  45. Introduction to mruby’s Objects in C

  46. 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
  47. 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;
  48. 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; };
  49. 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; };
  50. Class objects in depth

  51. mruby VM has class objects Proc String Float Fixnum Symbol

    Kernel Object Class Array Hash TrueClass FalseClass Module Range NilClass mrb_state (mruby VM)
  52. class has ivars and methods iv mt internal data methods

    class object (RClass) iv: instance variable mt: method table
  53. Ruby objects are struct in C struct RClass { MRB_OBJECT_HEADER;

    struct iv_tbl *iv; struct kh_mt *mt; struct RClass *super; };
  54. Memory Usage ‣Flash (ROM) ‣Heap (RAM) ‣use with malloc() ‣target

    of GC ‣Global variables (RAM) ‣use without malloc()
  55. 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
  56. Which’s in ROM, Which’s in RAM class mrb_state iv_tbl internal

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

    data methods GV ROM mt methods HEAP
  58. What’s structures in ROM ‣Objects (RBasic) ‣Symbols ‣Strings ‣IREPs ‣methods

    defined in initializing time ‣copy of VM (mrb_state)
  59. 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)
  60. Is it work? ‣You’ll get many problems ‣cannot define new

    classes ‣cannot use mrb_free() ‣cannot do GC ‣cannot use Object#freeze
  61. Is it work? ‣You’ll get many problems ‣cannot find (function|variable)

    names of C from (function|variable) addresses ‣need to generate C code
  62. Fix to work with ROM

  63. 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} }, /* ... */ };
  64. 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
  65. 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
  66. 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
  67. 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
  68. 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
  69. 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
  70. Benchmark

  71.      EFGBVMU  /7  

     
  72. Future works

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

  74. Special Thanks to: ‣ This work is supported Ruby Association

    grant program in 2018
  75. and Thank you!