ffi -- creating cross engine rubygems
DESCRIPTION
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.TRANSCRIPT
FFIMAKING CROSS ENGINE EXTENSIONS
Jeremy [email protected]
twitter : copiousfreetime
1Tuesday, November 24, 2009
I LOVE RUBY
2Tuesday, November 24, 2009
I LIKE C
3Tuesday, November 24, 2009
SURVEY TIME
4Tuesday, November 24, 2009
RUBY DEVELOPERS?
5Tuesday, November 24, 2009
WRITER OF LIBRARIES?
6Tuesday, November 24, 2009
WRITER OF EXTENSIONS?
7Tuesday, November 24, 2009
USED BY MULTIPLE ENGINES?
8Tuesday, November 24, 2009
WHAT IS FFI?
9Tuesday, November 24, 2009
LIBFFIhttp://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.”
10Tuesday, November 24, 2009
FOR RUBYISTS
The Goal :
An extension based upon FFI should be compatible with many ruby
engines.
11Tuesday, November 24, 2009
libfoo.so
12Tuesday, November 24, 2009
libfoo.so
Applicationuses
libfoo_bar()
12Tuesday, November 24, 2009
libfoo.so
Applicationuses
libfoo_bar()
FFI
12Tuesday, November 24, 2009
libfoo.so
Applicationuses
libfoo_bar()
FFIRuntim
e
12Tuesday, November 24, 2009
libfoo.so
ruby-foo C extension
Matz RubyInterpreter
App
13Tuesday, November 24, 2009
libfoo.so
ruby-foo C extension
Matz RubyInterpreter
App
JRubyInterpreter
App
RubiniusInterpreter
App
13Tuesday, November 24, 2009
libfoo.so
Matz RubyInterpreter
App
JRubyInterpreter
App
RubiniusInterpreter
App
13Tuesday, November 24, 2009
libfoo.so
Matz RubyInterpreter
App
JRubyInterpreter
App
RubiniusInterpreter
App
13Tuesday, November 24, 2009
libfoo.so
Matz RubyInterpreter
App
JRubyInterpreter
App
RubiniusInterpreter
App
built-in libffi or ffi gem
13Tuesday, November 24, 2009
libfoo.so
Matz RubyInterpreter
App
JRubyInterpreter
App
RubiniusInterpreter
App
built-in libffi or ffi gem
foo-ffi (pure ruby)
13Tuesday, November 24, 2009
LIBSIMPLE_METRICShttp://github.com/copiousfreetime/libsimple_metrics
14Tuesday, November 24, 2009
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
15Tuesday, November 24, 2009
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 ... end10 def mean ... end11 def min ... end12 def rate ... end13 def sum ... end14 def stddev ... end15 end
16Tuesday, November 24, 2009
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 }
17Tuesday, November 24, 2009
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 }
17Tuesday, November 24, 2009
7 module SimpleMetrics 8 module FFI 9 10 class Struct < ::FFI::ManagedStruct11 layout :min, :double, :max, :double, :sum, :double, 12 :sumsq, :double, :count, :long13 def self.release( ptr )14 SimpleMetrics::FFI.simple_metrics_free( ptr )15 end16 end17 18 extend ::FFI::Library19 ffi_lib "libsimple_metrics"20 21 attach_function :simple_metrics_new, [ ], :pointer22 attach_function :simple_metrics_free, [ :pointer ], :void23 attach_function :simple_metrics_update,[ :pointer, :double ], :void24 attach_function :simple_metrics_min, [ :pointer ], :double25 attach_function :simple_metrics_max, [ :pointer ], :double26 attach_function :simple_metrics_mean, [ :pointer ], :double27 attach_function :simple_metrics_sum, [ :pointer ], :double28 attach_function :simple_metrics_count, [ :pointer ], :long29 attach_function :simple_metrics_stddev,[ :pointer ], :double30 attach_function :simple_metrics_rate, [ :pointer ], :double31 32 end33 end
18Tuesday, November 24, 2009
7 module SimpleMetrics 8 module FFI 9 10 class Struct < ::FFI::ManagedStruct11 layout :min, :double, :max, :double, :sum, :double, 12 :sumsq, :double, :count, :long13 def self.release( ptr )14 SimpleMetrics::FFI.simple_metrics_free( ptr )15 end16 end17 18 extend ::FFI::Library19 ffi_lib "libsimple_metrics"20 21 attach_function :simple_metrics_new, [ ], :pointer22 attach_function :simple_metrics_free, [ :pointer ], :void23 attach_function :simple_metrics_update,[ :pointer, :double ], :void24 attach_function :simple_metrics_min, [ :pointer ], :double25 attach_function :simple_metrics_max, [ :pointer ], :double26 attach_function :simple_metrics_mean, [ :pointer ], :double27 attach_function :simple_metrics_sum, [ :pointer ], :double28 attach_function :simple_metrics_count, [ :pointer ], :long29 attach_function :simple_metrics_stddev,[ :pointer ], :double30 attach_function :simple_metrics_rate, [ :pointer ], :double31 32 end33 end
library function parameters return type
18Tuesday, November 24, 2009
35 module SimpleMetrics36 module FFI37 class Metric < ::SimpleMetrics::Common38 include ::SimpleMetrics::FFI39 def initialize( name )40 super41 @impl = FFI.simple_metrics_new42 end43 44 def update( v )45 simple_metrics_update( @impl, v )46 end47 48 self.keys.each do |f|49 module_eval <<-code50 def #{f}51 simple_metrics_#{f}( @impl )52 end53 code54 end55 end56 end57 end
19Tuesday, November 24, 2009
10 class Struct < ::FFI::ManagedStruct11 layout :min, :double, 12 :max, :double, 13 :sum, :double, 14 :sumsq, :double, 15 :count, :long16 def self.release( ptr )17 SimpleMetrics::FFI.simple_metrics_free( ptr )18 end19 end
6 typedef struct _simple_metrics{ 7 double min; 8 double max; 9 double sum;10 double sumsq;11 long count;12 } simple_metrics ;
20Tuesday, November 24, 2009
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 );
21 extend ::FFI::Library22 ffi_lib "libsimple_metrics"23 24 attach_function :simple_metrics_new, [ ], :pointer25 attach_function :simple_metrics_free, [ :pointer ], :void26 attach_function :simple_metrics_update,[ :pointer, :double ], :void27 attach_function :simple_metrics_mean, [ :pointer ], :double28 attach_function :simple_metrics_min, [ :pointer ], :double29 attach_function :simple_metrics_max, [ :pointer ], :double30 attach_function :simple_metrics_sum, [ :pointer ], :double31 attach_function :simple_metrics_count, [ :pointer ], :long32 attach_function :simple_metrics_stddev,[ :pointer ], :double33 attach_function :simple_metrics_rate, [ :pointer ], :double
21Tuesday, November 24, 2009
FFI Traditional C Extension
Jeremy’s Time
1 Million update() calls
Will it Blend run on JRuby?
40 minutes 70 minutes
1.16 sec 0.42 sec
Yes No
MEANINGLESS METRICS
22Tuesday, November 24, 2009
DEMO
23Tuesday, November 24, 2009
% ruby example/bench.rb 1000000generating 1000000 random numbers between 0 and 10,000Rehearsal -----------------------------------------------ext 0.500000 0.000000 0.500000 ( 0.504501)ffi 0.960000 0.000000 0.960000 ( 0.956847)-------------------------------------- total: 1.460000sec
user system total realext 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 1000000generating 1000000 random numbers between 0 and 10,000Rehearsal -----------------------------------------------ffi 0.697000 0.000000 0.697000 ( 0.696000)-------------------------------------- total: 0.697000sec
user system total realffi 0.493000 0.000000 0.493000 ( 0.493000)
24Tuesday, November 24, 2009
FFI BASED PROJECTS
Nokogiri ffi-wiiuse
Gnu Linear Programming Toolkit NiceFFI
Ruby-SDL-FFI
Rubygameffi-inliner
ffi-opengl
ffi-life
ffi-tccJohnson FFI port
rufus-tokyo
ffi-tk
Ruby-GIR-FFI
ffi-opencl
25Tuesday, November 24, 2009
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
26Tuesday, November 24, 2009
LINKS
• http://github.com/ffi/ffi
• http://wmeissner.blogspot.com/
• http://groups.google.com/group/ruby-ffi
27Tuesday, November 24, 2009
QUESTIONS?
28Tuesday, November 24, 2009