Fastruby - fast execution of ruby code
Fastruby is a gem which allows to execute ruby code faster than normal (about 20X of the MRI1.8)
Fastruby IS NOT a separated ruby interpreter. Then, the design is simple
Fastruby IS NOT a DSL to generate C code using ruby or a Ruby to C translator, the goal of fastruby is to execute RUBY code
*************************************************************************************************************
The current version of fastruby is a Proof of Concept and it’s not ready to go to production
*************************************************************************************************************
Core Concepts
Native build
All code processed by fastruby ends with a native representation, in the current version, this is acomplished using RubyParser to parse rubycode. The ruby code is translated to C and then processed with RubyInline
Transparent multimethods (and multiblocks)
The methods processed by fastruby has multiple internal implementations depending on the type of the arguments. Each possible signature has a version of the method and this are built in runtime when the method is called with a new signature. The same concept will be applied to blocks (anonymous methods) in future releases
Type inference
Each version of a method is built for a specific signature, so, the builder can asume a type for the arguments and build method calls using that assumption. Whereever the translator can asume a type for a expression involved in a method call (used as argument or as receiver), this information can be used to encode direct calls instead of normal and expensive ruby calls.
The currently implementation only can infer types for method and block arguments, and for literals
Method inlining
Type information is used to inline methods by replacing calls with the implementation of method being called. This greatly increase the performance WITHOUT breaking the expected dynamics of ruby code (e.g. allow replace an inlined method), many of corelib methods was reimplemented with ruby to allow inline them and increase the performance of code using corelib methods (e.g. Fixnum methods)
Customization through build directives and API
To compensate for the described limitations, fastruby suport a few build directives to allow the programmer help the inference. The syntaxis of these directives are the same as normal ruby call (see examples) Also, fastruby will define a API to customize aspects of fastruby internals. E.g the build method to invoke the build of methods with a specific signature (see examples)
Installation
The install is as simple as execute the well-known gem install:
sudo gem install fastruby
Documentation
Overhead due new frame structure of reduce the speed to 20x (previously was near 100X). This refactor was necessary to implement most of the common ruby constructions (blocks, yields, breaks, next, exceptions, etc…) Since this first version of fastruby is in part an spike/PoC, there is no stable API to document. So, I recommend not to develop other software on top of fastruby since its API could change in any moment. But I will try as much as possible keep the backward compatibility in the near future
I will stabilize the API and document it for next releases. I promise
Known Limitations & Issues
-
fastruby now works with ruby1.9, but features specific to ruby1.9 (such fibers and new hash notation) will not work or will work with unexpected behaviour
-
fastruby on ruby1.8 is faster than ruby1.8 on a few cases (see benchmarks) but is slower than ruby1.9
-
callcc is not supported, it works but using it may result in unexpected behaviour
-
calls with blocks to ruby or cruby methods are almost as slow as normal ruby (if the called method is defined by fastruby, the call is pretty fast)
Usage
Environment variables
FASTRUBY_LOG define the output file of logging (default is standard output) FASTRUBY_LOG_LEVEL define the logging level (default 3) FASTRUBY_NO_CACHE set to 1 to disable the cache globally
Fastruby options
This options can be passed to fastruby when defining fastruby blocks
:no_cache set to true to disable cache (default: false) :validate_lvar_vars enable runtime check of assignments of typed variable (default: disabled)
Code Examples
The basic method is fastruby, fastruby takes a string with ruby code and compile it
Example 1: How invoke fastruby
require "fastruby"
class X
fastruby '
def foo
print "hello world\n"
end
'
end
X.new.foo
Example 2: Prebuild
Normally, the method is built at runtime when is called with a new signature, You can prebuild the method to prevent this when the method is called for first time
require "fastruby"
class X
fastruby '
def foo(a,b)
a+b
end
'
end
X.build([X,String,String] , :foo)
p X.new.foo("fast", "ruby") # will use the prebuilded method
p X.new.foo(["fast"], ["ruby"]) # will build foo for X,Array,Array signature and then execute it
Example 3: Explicit inference
Current fastruby allows to explictly define a type for a expression, a basic example show as tell to fastruby to assume that the result of to_s is of type String in the following case:
require "fastruby"
class X
fastruby '
def foo(a)
a.to_s.infer(String) + "_"
end
'
end
p X.new.foo(9)
When fastruby can infer the type of an expression, the method calls that involve that expression can be accelerated. This is not necessary for arguments passed to a method or block
Example 4: Variable types
Like static languages, you can define a type for a variable to help the inference and gain some performance. This can be done by using lvar_type directive
class X
fastruby '
def foo
lvar_type(i, Fixnum)
i = 100
while (i > 0)
i = i - 1
end
nil
end
'
end
With no lvar_type, the calls to Fixnum#> and Fixnum#- will be dynamic and more expensive
Copying
Copyright © 2011 Dario Seminara, released under the GPL License (see LICENSE)