Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Inside Out Ruby: Using MRI as a C library - Artur Pyrogovskyi

8 views

Published on

Ruby Meditation #1
February 23, 2013
Kyiv

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Inside Out Ruby: Using MRI as a C library - Artur Pyrogovskyi

  1. 1. Вівторок, 19 березня 13 р.
  2. 2. Inside-Out Ruby: Using MRI as a C library Вівторок, 19 березня 13 р.
  3. 3. About me Arthur Pirogovski arthur@flyintealeaf.com Вівторок, 19 березня 13 р.
  4. 4. About me Coding for , mostly Ruby. Вівторок, 19 березня 13 р.
  5. 5. About me And C. segfault(87698) malloc: *** error for object 0x7fff5dbad6c0: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug Abort trap: 6 Вівторок, 19 березня 13 р.
  6. 6. About Ruby Вівторок, 19 березня 13 р.
  7. 7. About Ruby very readable Вівторок, 19 березня 13 р.
  8. 8. About Ruby “#{@str[:mostly]}” very readable Вівторок, 19 березня 13 р.
  9. 9. About Ruby very bad concurrency. Вівторок, 19 березня 13 р.
  10. 10. About Ruby Mediocre speed Вівторок, 19 березня 13 р.
  11. 11. About C Вівторок, 19 березня 13 р.
  12. 12. About C very unreadable void (*signal(int, void (*fp)(int)))(int); Вівторок, 19 березня 13 р.
  13. 13. About C concurrency is as good as your programming skills are Вівторок, 19 березня 13 р.
  14. 14. About C conc is urrencyaods go amings your program ls askilre Вівторок, 19 березня 13 р.
  15. 15. About C only FORTRAN is faster Вівторок, 19 березня 13 р.
  16. 16. About C Actually, not Вівторок, 19 березня 13 р.
  17. 17. Native Extensions Вівторок, 19 березня 13 р.
  18. 18. Native Extensions • great speedup • • Вівторок, 19 березня 13 р.
  19. 19. Native Extensions • great speedup • portability problems #ifdef • Вівторок, 19 березня 13 р.
  20. 20. Native Extensions • great speedup • portability problems #ifdef • secret concurrency (don’t tell Ruby) Вівторок, 19 березня 13 р.
  21. 21. What if we turn it inside out? Вівторок, 19 березня 13 р.
  22. 22. Strings “much”*10 easier in Ruby than in char ** C Вівторок, 19 березня 13 р.
  23. 23. DSL Turing-complete out of the box Вівторок, 19 березня 13 р.
  24. 24. DSL Turing-complete out of the box Pretty like drugs Вівторок, 19 березня 13 р.
  25. 25. Calling Ruby code - Hey, I’m C! (awkward silence) - Hey, I’m Ruby! Вівторок, 19 березня 13 р.
  26. 26. Garbage Collector Very bad one, but still better than none Вівторок, 19 березня 13 р.
  27. 27. Well-known APIs VALUE hash = rb_hash_new(); VALUE key = rb_string_new2(“key”); VALUE value = INT2FIX(42); rb_hash_aset(hash, key, value); rb_p(hash); Вівторок, 19 березня 13 р.
  28. 28. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif Вівторок, 19 березня 13 р.
  29. 29. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> Вівторок, 19 березня 13 р.
  30. 30. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int main() { ruby_init(); return 0; } Вівторок, 19 березня 13 р.
  31. 31. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int main() { ruby_init(); ruby_init_loadpath(); return 0; } Вівторок, 19 березня 13 р.
  32. 32. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int main() { ruby_init(); ruby_init_loadpath(); ruby_script("c.rb"); return 0; } Вівторок, 19 березня 13 р.
  33. 33. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int main() { ruby_init(); ruby_init_loadpath(); ruby_script("c.rb"); ruby_finalize(); return 0; } Вівторок, 19 березня 13 р.
  34. 34. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int main() { ruby_init(); ruby_init_loadpath(); ruby_script("c.rb"); VALUE ruby_string = rb_str_new2("Hi,I’m Ruby!"); rb_p(ruby_string); ruby_finalize(); return 0; } Вівторок, 19 березня 13 р.
  35. 35. MVP $ gcc minimal_embedded_ruby.c -o meruby -lruby -I ${MY_RUBY_HOME}/include/ruby-1.9.1 -I ${MY_RUBY_HOME}/include/ ruby-1.9.1/x86_64-linux -L $MY_RUBY_HOME/lib $ ./meruby "Hi from Ruby!" Note: $MY_RUBY_HOME is RVM-specific Вівторок, 19 березня 13 р.
  36. 36. Warning #1 Ruby can only be initialized from the main thread Вівторок, 19 березня 13 р.
  37. 37. Warning #2 DO NOT call ruby_run() It intercepts control flow and never returns. Вівторок, 19 березня 13 р.
  38. 38. Memory management Вівторок, 19 березня 13 р.
  39. 39. Memory management not fun. Вівторок, 19 березня 13 р.
  40. 40. This will SEGFAULT int main() { ruby_init(); ruby_init_loadpath(); ruby_script("c.rb"); VALUE ruby_string = rb_str_new2("Hi,I’m Ruby!"); rb_p(ruby_string); rb_gc(); rb_p(ruby_string); /* Right here */ ruby_finalize(); return 0; } Вівторок, 19 березня 13 р.
  41. 41. Registering vars #include <ruby.h> static VALUE ruby_objects; void lo(VALUE ruby_object) { rb_hash_aset(ruby_objects, rb_obj_id(ruby_object), ruby_object); } void uo(VALUE ruby_object) { rb_hash_delete(ruby_objects, rb_obj_id(ruby_object)); } Вівторок, 19 березня 13 р.
  42. 42. Registering vars int main() { ruby_init(); ... ruby_objects = rb_hash_new(); rb_global_variable(&ruby_objects); } Вівторок, 19 березня 13 р.
  43. 43. Registering vars int main() { ruby_init(); ... ruby_objects = rb_hash_new(); rb_global_variable(&ruby_objects); VALUE ruby_string = rb_str_new2("Hi from Ruby!"); } Вівторок, 19 березня 13 р.
  44. 44. Registering vars int main() { ruby_init(); ... ruby_objects = rb_hash_new(); rb_global_variable(&ruby_objects); VALUE ruby_string = rb_str_new2("Hi from Ruby!"); lo(ruby_string); rb_p(ruby_string); rb_gc(); } Вівторок, 19 березня 13 р.
  45. 45. Registering vars int main() { ruby_init(); ... ruby_objects = rb_hash_new(); rb_global_variable(&ruby_objects); VALUE ruby_string = rb_str_new2("Hi from Ruby!"); lo(ruby_string); rb_p(ruby_string); rb_gc(); rb_p(ruby_string); /* No SEGFAULT this time */ uo(ruby_string); ... } Вівторок, 19 березня 13 р.
  46. 46. GC tips call rb_gc() to collect can also be invoked by Ruby itself Вівторок, 19 березня 13 р.
  47. 47. GC tips always register variables rb_gc_register_address() is slow, so use some data structure Вівторок, 19 березня 13 р.
  48. 48. GC tips run rb_gc() often to detect problems early automatic GC can be disabled (dangerous!) Вівторок, 19 березня 13 р.
  49. 49. Exceptions Вівторок, 19 березня 13 р.
  50. 50. Exceptions are evil. Вівторок, 19 березня 13 р.
  51. 51. Exceptions rb_raise() rb_rescue() rb_ensure() Вівторок, 19 березня 13 р.
  52. 52. Exceptions rb_raise() is a longjmp() longjmp() skips your free()’s Вівторок, 19 березня 13 р.
  53. 53. Exceptions rb_protect() is a good catch-all wrapper Вівторок, 19 березня 13 р.
  54. 54. Exceptions int state = 0; rb_protect( RUBY_METHOD_FUNC(rb_require), (VALUE) “./code.rb”, &state); /* We couldn't execute rb_require */ if (state) { rb_p(rb_gv_get("$!")); exit(1); } Вівторок, 19 березня 13 р.
  55. 55. Functions: calling from C VALUE new_object = rb_funcall(some_class, rb_intern("new"), 1, arg1); Вівторок, 19 березня 13 р.
  56. 56. Functions: exporting to Ruby rb_define_singleton_method( some_class, “method_name”, method_name_in_c, -1) Вівторок, 19 березня 13 р.
  57. 57. Functions: exporting to Ruby static VALUE method_name_in_c(int argc, VALUE * argv, VALUE self) Вівторок, 19 березня 13 р.
  58. 58. Functions: exporting to Ruby rb_scan_args(argc, argv, “11”, &arg1, &arg2); Вівторок, 19 березня 13 р.
  59. 59. Speed For simple tasks, C-based loader is up to 4x faster Вівторок, 19 березня 13 р.
  60. 60. Speed But for complex tasks, speed gain is only about 15% Вівторок, 19 березня 13 р.
  61. 61. Speed Pure C code is up to 15x times faster Вівторок, 19 березня 13 р.
  62. 62. Docs README.EXT Vim’s if_ruby.c Ruby source code Вівторок, 19 березня 13 р.
  63. 63. Examples https://github.com/arp/ruby_from_c Вівторок, 19 березня 13 р.
  64. 64. Thanks Questions? Вівторок, 19 березня 13 р.
  65. 65. Bonus FastCGI + Ruby + C Вівторок, 19 березня 13 р.

×