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 <math.h>
#include <stdio.h>

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