From: ptkwt@... (Phil Tomson) Date: 2005-07-22T05:40:57+09:00 Subject: Re: C extension makes things slower In article <20050721175902.GH2279@tux-chan>, Mauricio Fern�ndez wrote: >On Fri, Jul 22, 2005 at 02:05:56AM +0900, Phil Tomson wrote: >> In article <42DF4F1D.2060607@capitain.de>, >> Pit Capitain wrote: >> >Phil Tomson schrieb: >> >> And the results: >> >> l% ruby point.rb >> >> Total time for pure ruby point test: 8.600752 >> >> ACO_Ext initializing... >> >> Total time for extension point test: 6.086567 >> However, here's the result of another run: >> >> Total time for pure ruby point test: 8.051388 >> ACO_Ext initializing... >> Total time for extension point test: 9.212984 > >You're doing things like > >static VALUE aco_point_diff(VALUE self, VALUE other){ > double self_x = NUM2DBL(rb_iv_get(self, "@x")); > double self_y = NUM2DBL(rb_iv_get(self, "@y")); > double other_x= NUM2DBL(rb_iv_get(other, "@x")); > double other_y= NUM2DBL(rb_iv_get(other, "@y")); > double xdiffsq= pow( (self_x - other_x),2 ); > double ydiffsq= pow( (self_y - other_y),2 ); > return rb_float_new(sqrt( xdiffsq + ydiffsq ) ); > >} > >when you probably want something resembling > >typedef struct { > double x; > double y; >} ACO_Point_Struct; > >static VALUE >aco_point_diff(VALUE self, VALUE other) >{ > ACO_Point_Struct *_self, *_other; > double dx, dy; > > Data_Get_Struct(self, ACO_Point_Struct, _self); > Data_Get_Struct(other, ACO_Point_Struct, _other); > > dx = _self->x - _other->x; > dy = _self->y - _other->y; > return rb_float_new(sqrt(dx * dx + dy * dy)); >} > Thanks, that's _MUCH_ (and consistently) faster: $ ruby point.rb Total time for pure ruby point test: 6.977688 ACO_Ext initializing... Total time for extension point test: 2.777282 And now my real application that uses point is much faster too: $ruby TSP.rb -->best tour in gen 0: 8667.97295111485 -->global best tour is: 8128.7749762166 Total time: 3.635439 ....used to be something like 22 seconds. Oh, for the sake of complete documentation in case someone has similar questions in the future: I had to add an allocate function so here's the new version of aco_ext.c: //aco_ext.c #include "ruby.h" #include #include static int id_x; static int id_y; static int id_equal; typedef struct { double x; double y; } ACO_Point_Struct; static void aco_point_free(void* p){ free(p); } static VALUE aco_point_alloc(VALUE klass) { VALUE object; ACO_Point_Struct* point = (ACO_Point_Struct*)malloc(sizeof( ACO_Point_Struct)); object = Data_Wrap_Struct(klass,0,aco_point_free,point); return object; } static VALUE aco_point_init(VALUE self, VALUE x, VALUE y){ ACO_Point_Struct* _self ; //double x, y; Data_Get_Struct(self, ACO_Point_Struct, _self); _self->x = NUM2DBL(x); _self->y = NUM2DBL(y); return self; } static VALUE aco_point_diff(VALUE self, VALUE other) { ACO_Point_Struct *_self, *_other; double dx, dy; Data_Get_Struct(self, ACO_Point_Struct, _self); Data_Get_Struct(other, ACO_Point_Struct, _other); dx = _self->x - _other->x; dy = _self->y - _other->y; return rb_float_new(sqrt(dx * dx + dy * dy)); } static VALUE aco_point_equal(VALUE self, VALUE other){ ACO_Point_Struct *_self; ACO_Point_Struct *_other; double x, y; Data_Get_Struct(self, ACO_Point_Struct, _self); Data_Get_Struct(other, ACO_Point_Struct, _other); return((_self->x == _other->x) && (_self->y == _other->y)); } VALUE cACOMod; VALUE cACOPoint; VALUE cACOGraph; void Init_ACO_Ext() { printf("ACO_Ext initializing...\n"); cACOMod = rb_define_module("ACO"); cACOPoint = rb_define_class_under(cACOMod,"Point",rb_cObject); cACOGraph = rb_define_class_under(cACOMod,"Graph",rb_cObject); rb_define_alloc_func(cACOPoint, aco_point_alloc); rb_define_method(cACOPoint,"initialize",aco_point_init,2); rb_define_method(cACOPoint,"-",aco_point_diff,1); rb_define_method(cACOPoint,"==",aco_point_equal,1); id_x = rb_intern("x"); id_y = rb_intern("y"); id_equal = rb_intern("=="); } //end aco_ext.c Phil