FFI -- creating cross engine rubygems

  • 1,575 views
Uploaded on

FFI is a way to create cross engine rubygems. Wrap a library once, and use it from MRI, JRuby, Rubinious, and mingw32 Ruby. This talk will discuss FFI why you want to use it.

FFI is a way to create cross engine rubygems. Wrap a library once, and use it from MRI, JRuby, Rubinious, and mingw32 Ruby. This talk will discuss FFI why you want to use it.

More in: Technology , Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,575
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
18
Comments
0
Likes
4

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. FFI MAKING CROSS ENGINE EXTENSIONS Jeremy Hinegardner jeremy@copiousfreetime.org twitter: copiousfreetime Tuesday, November 24, 2009 1
  • 2. I LOVE RUBY Tuesday, November 24, 2009 2
  • 3. I LIKE C Tuesday, November 24, 2009 3
  • 4. SURVEY TIME Tuesday, November 24, 2009 4
  • 5. RUBY DEVELOPERS? Tuesday, November 24, 2009 5
  • 6. WRITER OF LIBRARIES? Tuesday, November 24, 2009 6
  • 7. WRITER OF EXTENSIONS? Tuesday, November 24, 2009 7
  • 8. USED BY MULTIPLE ENGINES? Tuesday, November 24, 2009 8
  • 9. WHAT IS FFI? Tuesday, November 24, 2009 9
  • 10. LIBFFI http://sourceware.org/libffi/ “A foreign function interface is the popular name for the interface that allows code written in one language to call code written in another language.” Tuesday, November 24, 2009 10
  • 11. FOR RUBYISTS The Goal : An extension based upon FFI should be compatible with many ruby engines. Tuesday, November 24, 2009 11
  • 12. libfoo.so Tuesday, November 24, 2009 12
  • 13. Application uses libfoo_bar() libfoo.so Tuesday, November 24, 2009 12
  • 14. Application uses libfoo_bar() FFI libfoo.so Tuesday, November 24, 2009 12
  • 15. m e i Application t n uses R u libfoo_bar() FFI libfoo.so Tuesday, November 24, 2009 12
  • 16. App Matz Ruby Interpreter ruby-foo C extension libfoo.so Tuesday, November 24, 2009 13
  • 17. App App JRuby Rubinius Interpreter Interpreter App Matz Ruby Interpreter ruby-foo C extension libfoo.so Tuesday, November 24, 2009 13
  • 18. App App JRuby Rubinius Interpreter Interpreter App Matz Ruby Interpreter libfoo.so Tuesday, November 24, 2009 13
  • 19. App App App JRuby Matz Ruby Rubinius Interpreter Interpreter Interpreter libfoo.so Tuesday, November 24, 2009 13
  • 20. App App App JRuby Matz Ruby Rubinius Interpreter Interpreter Interpreter built-in libffi or ffi gem libfoo.so Tuesday, November 24, 2009 13
  • 21. App App App JRuby Matz Ruby Rubinius Interpreter Interpreter Interpreter foo-ffi (pure ruby) built-in libffi or ffi gem libfoo.so Tuesday, November 24, 2009 13
  • 22. LIBSIMPLE_METRICS http://github.com/copiousfreetime/libsimple_metrics Tuesday, November 24, 2009 14
  • 23.  1 #ifndef __SIMPLE_METRICS_H__  2 #define __SIMPLE_METRICS_H__  3 #include <stdlib.h>  4 #include <math.h>  5  6 typedef struct _simple_metrics{  7     double min;  8     double max;  9     double sum; 10     double sumsq; 11     long   count; 12 } simple_metrics ; 13 14 simple_metrics* simple_metrics_new(); 15 void            simple_metrics_free(   simple_metrics* sm ); 16 void            simple_metrics_update( simple_metrics* sm, double value ); 17 double          simple_metrics_mean(   simple_metrics* sm ); 18 double          simple_metrics_min(    simple_metrics* sm ); 19 double          simple_metrics_max(    simple_metrics* sm ); 20 double          simple_metrics_sum(    simple_metrics* sm ); 21 long            simple_metrics_count(  simple_metrics* sm ); 22 double          simple_metrics_stddev( simple_metrics* sm ); 23 double          simple_metrics_rate(   simple_metrics* sm ); 24 25 #endif Tuesday, November 24, 2009 15
  • 24.  1 class Metric  2   attr_reader :name  3   def initialize( name )  4     @name  5   end  6  7   def update( new_value) ... end  8   def count  ... end  9   def max    ... end 10   def mean   ... end 11   def min    ... end 12   def rate   ... end 13   def sum    ... end 14   def stddev ... end 15 end Tuesday, November 24, 2009 16
  • 25. 142 void Init_simple_metrics_ext() 143 { 144     VALUE cSM_Common; 145 146     mSM  = rb_define_module( "SimpleMetrics" ); 147     mSME = rb_define_module_under( mSM, "Ext" ); 148 149     /* load the class we inherit from */ 150     rb_require("simplemetrics/common"); 151 152     cSM_Common = rb_const_get( mSM, rb_intern( "Common" ) ); 153 154     cSME_Metric = rb_define_class_under( mSME, "Metric", cSM_Common ); 155 156     rb_define_alloc_func(cSME_Metric, sm_alloc); 157     rb_define_method( cSME_Metric, "initialize", sm_initialize, 1 ); 158     rb_define_method( cSME_Metric, "update", sm_update, 1 ); 159     rb_define_method( cSME_Metric, "count", sm_count, 0 ); 160     rb_define_method( cSME_Metric, "max", sm_max, 0 ); 161     rb_define_method( cSME_Metric, "min", sm_min, 0 ); 162     rb_define_method( cSME_Metric, "mean", sm_mean, 0 ); 163     rb_define_method( cSME_Metric, "rate", sm_rate, 0 ); 164     rb_define_method( cSME_Metric, "sum", sm_sum, 0 ); 165     rb_define_method( cSME_Metric, "stddev", sm_stddev, 0 ); 166 167 } Tuesday, November 24, 2009 17
  • 26. 142 void Init_simple_metrics_ext() 143 { 144     VALUE cSM_Common; 145 146     mSM  = rb_define_module( "SimpleMetrics" ); 147     mSME = rb_define_module_under( mSM, "Ext" ); 148 149     /* load the class we inherit from */ 150     rb_require("simplemetrics/common"); 151 152     cSM_Common = rb_const_get( mSM, rb_intern( "Common" ) ); 153 154     cSME_Metric = rb_define_class_under( mSME, "Metric", cSM_Common ); 155 156     rb_define_alloc_func(cSME_Metric, sm_alloc); 157     rb_define_method( cSME_Metric, "initialize", sm_initialize, 1 ); 158     rb_define_method( cSME_Metric, "update", sm_update, 1 ); 159     rb_define_method( cSME_Metric, "count", sm_count, 0 ); 160     rb_define_method( cSME_Metric, "max", sm_max, 0 ); 161     rb_define_method( cSME_Metric, "min", sm_min, 0 ); 162     rb_define_method( cSME_Metric, "mean", sm_mean, 0 ); 163     rb_define_method( cSME_Metric, "rate", sm_rate, 0 ); 164     rb_define_method( cSME_Metric, "sum", sm_sum, 0 ); 165     rb_define_method( cSME_Metric, "stddev", sm_stddev, 0 ); 166 167 } Tuesday, November 24, 2009 17
  • 27. 7 module SimpleMetrics  8   module FFI  9 10     class Struct < ::FFI::ManagedStruct 11       layout :min, :double, :max, :double, :sum, :double, 12              :sumsq, :double, :count, :long 13       def self.release( ptr ) 14         SimpleMetrics::FFI.simple_metrics_free( ptr ) 15       end 16     end 17 18     extend ::FFI::Library 19     ffi_lib "libsimple_metrics" 20 21     attach_function :simple_metrics_new,   [          ], :pointer 22     attach_function :simple_metrics_free,  [ :pointer ], :void 23     attach_function :simple_metrics_update,[ :pointer, :double  ], :void 24     attach_function :simple_metrics_min,   [ :pointer ], :double 25     attach_function :simple_metrics_max,   [ :pointer ], :double 26     attach_function :simple_metrics_mean,  [ :pointer ], :double 27     attach_function :simple_metrics_sum,   [ :pointer ], :double 28     attach_function :simple_metrics_count, [ :pointer ], :long 29     attach_function :simple_metrics_stddev,[ :pointer ], :double 30     attach_function :simple_metrics_rate,  [ :pointer ], :double 31 32   end 33 end Tuesday, November 24, 2009 18
  • 28. 7 module SimpleMetrics  8   module FFI  9 10     class Struct < ::FFI::ManagedStruct 11       layout :min, :double, :max, :double, :sum, :double, 12              :sumsq, :double, :count, :long 13       def self.release( ptr ) 14         SimpleMetrics::FFI.simple_metrics_free( ptr ) 15       end 16     end library function parameters return type 17 18     extend ::FFI::Library 19     ffi_lib "libsimple_metrics" 20 21     attach_function :simple_metrics_new,   [          ], :pointer 22     attach_function :simple_metrics_free,  [ :pointer ], :void 23     attach_function :simple_metrics_update,[ :pointer, :double  ], :void 24     attach_function :simple_metrics_min,   [ :pointer ], :double 25     attach_function :simple_metrics_max,   [ :pointer ], :double 26     attach_function :simple_metrics_mean,  [ :pointer ], :double 27     attach_function :simple_metrics_sum,   [ :pointer ], :double 28     attach_function :simple_metrics_count, [ :pointer ], :long 29     attach_function :simple_metrics_stddev,[ :pointer ], :double 30     attach_function :simple_metrics_rate,  [ :pointer ], :double 31 32   end 33 end Tuesday, November 24, 2009 18
  • 29. 35 module SimpleMetrics 36   module FFI 37     class Metric < ::SimpleMetrics::Common 38       include ::SimpleMetrics::FFI 39       def initialize( name ) 40         super 41         @impl = FFI.simple_metrics_new 42       end 43 44       def update( v ) 45         simple_metrics_update( @impl, v ) 46       end 47 48       self.keys.each do |f| 49         module_eval <<-code 50         def #{f} 51           simple_metrics_#{f}( @impl ) 52         end 53         code 54       end 55     end 56   end 57 end Tuesday, November 24, 2009 19
  • 30. 10 class Struct < ::FFI::ManagedStruct  6 typedef struct _simple_metrics{ 11   layout :min, :double,  7     double min; 12          :max, :double,  8     double max; 13          :sum, :double,  9     double sum; 14          :sumsq, :double, 10     double sumsq; 15          :count, :long 11     long   count; 16   def self.release( ptr ) 12 } simple_metrics ; 17     SimpleMetrics::FFI.simple_metrics_free( ptr ) 18   end 19 end Tuesday, November 24, 2009 20
  • 31. 21 extend ::FFI::Library 22 ffi_lib "libsimple_metrics" 23 24 attach_function :simple_metrics_new,   [          ], :pointer 25 attach_function :simple_metrics_free,  [ :pointer ], :void 26 attach_function :simple_metrics_update,[ :pointer, :double  ], :void 27 attach_function :simple_metrics_mean,  [ :pointer ], :double 28 attach_function :simple_metrics_min,   [ :pointer ], :double 29 attach_function :simple_metrics_max,   [ :pointer ], :double 30 attach_function :simple_metrics_sum,   [ :pointer ], :double 31 attach_function :simple_metrics_count, [ :pointer ], :long 32 attach_function :simple_metrics_stddev,[ :pointer ], :double 33 attach_function :simple_metrics_rate,  [ :pointer ], :double 14 simple_metrics* simple_metrics_new(); 15 void            simple_metrics_free(   simple_metrics* sm ); 16 void            simple_metrics_update( simple_metrics* sm, double value ); 17 double          simple_metrics_mean(   simple_metrics* sm ); 18 double          simple_metrics_min(    simple_metrics* sm ); 19 double          simple_metrics_max(    simple_metrics* sm ); 20 double          simple_metrics_sum(    simple_metrics* sm ); 21 long            simple_metrics_count(  simple_metrics* sm ); 22 double          simple_metrics_stddev( simple_metrics* sm ); 23 double          simple_metrics_rate(   simple_metrics* sm ); Tuesday, November 24, 2009 21
  • 32. MEANINGLESS METRICS Traditional C FFI Extension Jeremy’s Time 40 minutes 70 minutes 1 Million update() 1.16 sec 0.42 sec calls Will it Blend run Yes No on JRuby? Tuesday, November 24, 2009 22
  • 33. DEMO Tuesday, November 24, 2009 23
  • 34. % ruby example/bench.rb 1000000 generating 1000000 random numbers between 0 and 10,000 Rehearsal ----------------------------------------------- ext 0.500000 0.000000 0.500000 ( 0.504501) ffi 0.960000 0.000000 0.960000 ( 0.956847) -------------------------------------- total: 1.460000sec user system total real ext 0.510000 0.000000 0.510000 ( 0.521388) ffi 0.940000 0.000000 0.940000 ( 0.946538) % ~/pkgs/jruby-1.4.0/bin/jruby example/bench.rb 1000000 generating 1000000 random numbers between 0 and 10,000 Rehearsal ----------------------------------------------- ffi 0.697000 0.000000 0.697000 ( 0.696000) -------------------------------------- total: 0.697000sec user system total real ffi 0.493000 0.000000 0.493000 ( 0.493000) Tuesday, November 24, 2009 24
  • 35. FFI BASED PROJECTS ffi-opengl Johnson FFI port ffi-tk ffi-tcc Nokogiri Ruby-SDL-FFI ffi-wiiuse ffi-life ffi-opencl rufus-tokyo ffi-inliner Rubygame Ruby-GIR-FFI Gnu Linear Programming Toolkit NiceFFI Tuesday, November 24, 2009 25
  • 36. THANKS • Wayne Meissner - adding libffi to JRuby and providing the ffi gem for MRI. • Evan Phoenix - using libffi in Rubinius • Authors of the examples on the ffi project wiki Tuesday, November 24, 2009 26
  • 37. LINKS • http://github.com/ffi/ffi • http://wmeissner.blogspot.com/ • http://groups.google.com/group/ruby-ffi Tuesday, November 24, 2009 27
  • 38. QUESTIONS? Tuesday, November 24, 2009 28