rdp / crystalizer forked from smtlaissezfaire/ruby2cext

crystalizer--it takes your ruby code and crystalizes it into a much faster form by c-ifying it (originally based off ruby2cext code). Can result in up to 5X the speed of 1.9

This URL has Read+Write access

name age message
file Changelog Mon Jun 11 19:32:30 -0700 2007 updated README and Changelog git-svn-id: http:... [dbat]
file README Tue Dec 22 16:31:20 -0800 2009 move README around [rdp]
file Rakefile Sat Nov 07 20:51:47 -0800 2009 update gemspec [rdp]
file TODO Fri Oct 02 16:37:54 -0700 2009 attempt to avoid concretizing anonymous classes... [rdp]
file VERSION Sat Nov 07 20:51:47 -0800 2009 update gemspec [rdp]
directory benchmarks/ Sat Nov 07 21:20:42 -0800 2009 add extconf [rdp]
directory bin/ Sat Nov 07 17:44:26 -0800 2009 add some notes--note that I believe this versio... [rdp]
directory doc/ Mon Sep 28 13:46:58 -0700 2009 almost got concretizer working... [rdp]
directory lib/ Tue Nov 10 13:15:12 -0800 2009 cache works now [rdp]
file results Thu Nov 12 05:38:59 -0800 2009 clarify README [rdp]
file setup.rb Fri Jun 16 17:35:31 -0700 2006 initial commit git-svn-id: http://ruby2cext.ru... [dbat]
directory stuff/ Sun Sep 10 12:07:24 -0700 2006 more 1.8.5 changes and some other things git-s... [dbat]
directory test/ Tue Nov 10 13:06:20 -0800 2009 add cacheing--if only it worked... [rdp]
README
----------- Crystalizer -------------

The crystalizer gem is basically a "user friendly" wrapper for a ruby2c converter called ruby2cext.  It takes your ruby 
code, creates its rubyC equivalent, and replaces the existing ruby methods with their C "optimized" equivalents, 
effectively JIT-ing existing Ruby code.  

It is called crystalizer because you create your code first in ruby, then "crystalize" it to C.  It also does call 
location cacheing, thus it is crystalizing the method call lookups so they can be done in C instead of Ruby, making it 
faster.

It currently uses most of the optional optimizations that ruby2cext provides, to try and squeeze out as much speed as 
possible.

On some artificial benchmarks, it has run at up to 5x the speed of 1.9 
(http://github.com/rdp/crystalizer/blob/master/results), though it's unclear if it actually provides any speedup in the 
real world, over 1.9.  If not then updating it to be 1.9 compatible might do the trick.

---- Usage ----

require 'concretizer'

Klass.concretize! # concretizes all interior methods of this class, and methods of its ancestors

or, if you have several classes and don't want to have to remember exactly which ones to concretize, you can pass it a 
block.

Ruby2CExtension::Concretize.crystalize_after_first_time_through {
    # do some stuff here
    # after completing this block, it will concretize any and all classes run within the block
    # so the first time through will slower than usual, and second and third times should be faster [or any other code 
    that subsequently calls those classes]
    # still a bit buggy
}

And for the daring, concretize all classes thus:

Ruby2CExtension::Conretize.concretize_all!  # crystalizes all existing classes -- takes forever, you might discover bugs 
in edge cases that aren't covered yet--but should speed up everything, and it does pass its unit tests, at least.  
Report bugs back to me.

Also an option is the included rb2cx executable
$ rb2cx ruby_filename.rb

which creates ruby_filename.{c, so} based on ruby_filename.rb.

Thus you could run the ruby script's c equivalent thus:
$ ruby -rruby_filename.so -e ''

or with optimizations turned on:
$ rb2cx ruby_filename.rb -O all


Currently the safest/sanest way is to use rb2cx to convert a single file into C, then use that file's .so

Caveats:

Some of the optimizations make some speed-up enabling assumptions (like that you won't be overwriting any constants [you 
don't anyway, right?], and won't be overwriting defined methods).  It therefore isn't 100% pure ruby compatible, and it 
also loses backtrace information (though there is an option to turn on some backtrace info--it is quite faster without 
it).  It has thus proven quite a bit faster than 1.9 in some benchmarks, though it is currently a 1.8 only library 
[presumably if it were made 1.9 compatible, it might be even faster, because the stdlib for 1.9 seems to be faster].

Crystalize only crystalizes methods--it doesn't crystalize proc objects in the system--they stay as pure Ruby--it does 
crystalize procs created from within crystalized methods, though, which is typically probably good enough. 

Note that you will need the rubynode gem, see below.

Also note: not 1.9 compat. currently, though this is probably a high-ish priority, should I ever want more speed than it 
currently gives :).  Should it ever become so, you may want to cache your eval'ed methods, so that they can be optimized 
[only methods from a real file can be found again, and optimized].

Usages:
You could theoretically use this to crystalize slow parts of your code, or a gem packager could even distribute a "pure 
ruby" and "crystalized" version of their code, let your imagination go wild.


Feedback welcome: http://github.com/rdp/crystalizer

If you have a special use case ["I use int's a lot for mandelbrot!"] or what not let me know--I might be able to 
optimize crystalizer to accomodate for it [by inlining math, etc.]


Speed notes:  Using local variables are much faster, after which in speed is (I think) using constants, then instance 
variables (i.e. instance variables can be slow, if you're looking for raw speed).  You may be able to use and get some 
speed up if you can use constants instead of instance variables...

Ex:
A = {}

def go
 A.clear
  # do some stuff with A, as long as you're single threaded and can leave it at the end.
end

Though I haven't speed tested this hypothesis yet.


Much thanks to the original author of Ruby2CExtension, since this is only a wrapper to his work, basically, with some 
minor changes.

Mailing list: http://groups.google.com/group/ruby-optimization


Ruby2CExtension (begin original README)...
===============

Ruby2CExtension is a Ruby to C extension translator/compiler. It takes any Ruby
source file, parses it using Ruby's builtin parser and then translates the
abstract syntax tree into "equivalent" C extension code.


Requirements
------------

* Ruby 1.8.4, 1.8.5 or 1.8.6 (possibly 1.8.7--haven't tried)
* RubyNode (available at http://rubynode.rubyforge.org/) 


Installation
------------

Just run (as root): TODO make this easier

  gem install ruby2cext
  # you may need to download the source files for your ruby distro--follow instructions if gem install failure

Documentation
-------------

Please see doc/index.html for more documentation.




License
-------

Copyright 2006-2007 Dominik Bathon <dbatml@gmx.de>

Ruby2CExtension is licensed under the same terms as Ruby.