From: ptkwt@... (Phil Tomson) Date: 2005-07-21T16:15:56+09:00 Subject: C extension makes things slower In general I've always seen things speed up when I've writtten C extensions. I usually don't rewrite all of the methods in a class, just certain speed critical ones. In this case I've got a Point class: #point.rb module ACO class Point attr_accessor :x, :y def initialize(x,y) @x = x @y = y end #calculate the distance between this point and other point def -(other) Math.sqrt((@x-other.x)**2+(@y-other.y)**2) end def ==(other) return (@x == other.x) && (@y == other.y) end def to_s "(#{@x},#{@y})" end end end #ACO if $0 == __FILE__ start_time = Time.now 100000.times do |i| p1 = ACO::Point.new(rand(50),rand(50)) p2 = ACO::Point.new(rand(50),rand(50)) p1 == p2 p2 == p1 p1-p2 p2-p1 end end_time = Time.now puts "Total time for pure ruby point test: #{end_time - start_time}" require 'ext/ACO_Ext' #load up the extension bundle start_time = Time.now 100000.times do |i| p1 = ACO::Point.new(rand(50),rand(50)) p2 = ACO::Point.new(rand(50),rand(50)) p1 == p2 p2 == p1 p1-p2 p2-p1 end end_time = Time.now puts "Total time for extension point test: #{end_time - start_time}" end #point.rb Here's the C code for the extension: //aco_ext.c #include "ruby.h" #include #include static int id_x; static int id_y; static int id_equal; 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 ) ); } static VALUE aco_point_init(VALUE self, VALUE x, VALUE y){ rb_iv_set(self,"@x",x); rb_iv_set(self,"@y",y); return self; } static VALUE aco_point_equal(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")); 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_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 of aco_ext.c 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 Using the extension it's 2.6 second _slower_ than the pure Ruby implementation!? Phil