UPDATE: Fixnum#gcd
was accepted int MRI 1.8: See https://devdriven.com/2010/02/ruby-fixnumgcd-accepted-into-mri/ .
Ruby Date
uses Rational
heavily, which calls Integer#gcd
for every new Rational
. The Integer#gcd
method is generic to handle Bignums
, but performs terribly for Fixnum#gcd(Fixnum)
, which is probably the most often case.
This RubyInline hack saved 15% execution time in a large Rails application:
require 'inline' class Fixnum inline do | builder | builder.c_raw ' static VALUE gcd(int argc, VALUE *argv, VALUE self) { if ( argc != 1 ) { rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, 1); } /* Handle Fixnum#gcd(Fixnum) case directly. */ if ( FIXNUM_P(argv[0]) ) { /* fprintf(stderr, "Using Fixnum#gcd(Fixnum)\n"); */ long a = FIX2LONG(self); long b = FIX2LONG(argv[0]); long min = a < 0 ? - a : a; long max = b < 0 ? - b : b; while ( min > 0 ) { int tmp = min; min = max % min; max = tmp; } return LONG2FIX(max); } else { /* fprintf(stderr, "Using super#gcd\n"); */ return rb_call_super(1, argv); } } ' end end
Update:
Sorry for the late reply. If the code above does not work via cut-and-paste, download it from here.
This will be released soon as a gem dynamic library called speedfreaks,
with other performance-enhancing snippets.
Thanks for the feedback!