26
FFI MAKING CROSS ENGINE EXTENSIONS Jeremy Hinegardner [email protected] twitter: copiousfreetime

Ffi

Embed Size (px)

Citation preview

Page 1: Ffi

FFIMAKING CROSS ENGINE EXTENSIONS

Jeremy [email protected]

twitter : copiousfreetime

Page 2: Ffi

COPIOUS FREE TIME

Fedora Packaging

•beanstalkd•haproxy•libtomcrypt•libtommath•nginx•ragel•tinyproxy

Ruby Gems

•keybox•rabal•launchy•heel•htauth•amalgalite•hitimes•stickler•crate

Page 3: Ffi

I LOVE RUBY

Page 4: Ffi

I LIKE C

Page 5: Ffi

ANYEXTENSION DEVELOPERS

IN THE HOUSE ?

Page 6: Ffi

WHO HAS USED FFI?

Page 7: Ffi

WHO HAS HEARD OF FFI?

Page 8: Ffi

WHAT IS FFI?

Page 9: Ffi

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.”

Page 10: Ffi

libsomething.so

Applicationuses

libsomething_foo()

FFIRuntim

e

Page 11: Ffi

libsomething.so

ruby-something C extension

Matz RubyInterpreter

App

JRubyInterpreter

App

RubiniusInterpreter

App

built-in libffi or ffi gem

something-ffi (pure ruby)

Page 12: Ffi

 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

Page 13: Ffi

 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

Page 14: Ffi

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 }

Page 15: Ffi

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

Page 16: Ffi

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

Page 17: Ffi

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 ;

Page 18: Ffi

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

Page 19: Ffi

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

Page 20: Ffi

% ruby ~/Projects/simple_metrics/example/bench.rb 1000000generating 1000000 random numbers between 0 and 10,000Rehearsal -----------------------------------------------ext 0.420000 0.000000 0.420000 ( 0.460806)ffi 1.160000 0.000000 1.160000 ( 1.171498)-------------------------------------- total: 1.580000sec

user system total realext 0.420000 0.010000 0.430000 ( 0.424809)ffi 1.160000 0.000000 1.160000 ( 1.182928)

% ./bin/jruby ~/Projects/simple_metrics/example/bench.rb 1000000generating 1000000 random numbers between 0 and 10,000Skipping ExtRehearsal -----------------------------------------------ffi 0.922000 0.000000 0.922000 ( 0.922000)-------------------------------------- total: 0.922000sec

user system total realffi 0.834000 0.000000 0.834000 ( 0.834000)

Page 21: Ffi

FFI GEMS

4ffi-ncurses

ffi-swig-generator ffi-zlib

tidy_ffi

Page 22: Ffi

GEMS WITH EXTENSIONS

346Out of 4,501 gems

Page 23: Ffi

GETTO

WORK!!

Page 24: Ffi

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 Project Kenai wiki

Page 25: Ffi

LINKS

• http://blog.headius.com/2008/10/ffi-for-ruby-now-available.html

• http://kenai.com/projects/ruby-ffi

• http://wmeissner.blogspot.com/

• http://www.igvita.com/2009/01/15/bridging-mri-jruby-rubinius-with-ffi/

• http://blog.segment7.net/articles/2008/01/15/rubinius-foreign-function-interface

Page 26: Ffi

QUESTIONS?