Although JRuby's performance is close to Cruby, sometimes it's still not fast enough. Cruby users can use Ryan Davis's Rubyinline Library, which provides built-in support for C + + to make it easier to generate Ruby's C extensions. Charles Nutter from the JRuby camp has now implemented a Rubyinline builder for JRuby, which can instantly compile embedded Java code.
The following is an example of a factorial calculation method written using C by Ryan Davis:
class MyTest
inline do |builder|
builder.c "
long factorial_c(int max) {
int i=max, result=1;
while (i >= 2) { result *= i--; }
return result;
}
"
end
end
The following are the corresponding JRuby implementations provided by Charles:
class FastMath
inline :Java do |builder|
builder.package "org.jruby.test"
builder.java "
public static long factorial_java(int max) {
int i=max, result=1;
while (i >= 2) { result *= i--; }
return result;
}
"
end
end
One disadvantage of rubyinline for JRuby is that it requires a Java 6 JDK (for compilers) that it may not yet be available on all systems.
Another way to generate fast code execution is to generate JVM bytecode directly. This sounds a bit drastic for normal applications, and bytecode generation tools like compilers can benefit from a simple bytecode generation DSL, as mentioned in the blog of Charles Nutter earlier. However, even the use of DSL to generate bytecode is not easy. Here's an example of Charles's blog: A method named Bar adds a lowercase string parameter to the incoming ArrayList, and the following is the resulting code:
def test_class_builder
cb = Compiler::ClassBuilder.build("MyClass", "MyClass.java") do
[...]
method(:bar, ArrayList, String, ArrayList) do
aload 1
invokevirtual(String, :toLowerCase, String)
aload 2
swap
invokevirtual(ArrayList, :add, [Boolean::TYPE, Object])
aload 2
areturn
end
[...]
Charles Nutter also offers a new program called Duby, which implements a subset of the Ruby syntax, enhances some type inference logic (please visit Charles ' blog for more information), and generates fast bytecode. The following is also the method for calculating the factorial, which is written for the Duby compiler.
class Fac
def self.fac(max)
{max => :int, :return => :int}
i = max
result = 1
while i > 1
result *= i
i -= 1
end
result
end
end
This is a prototype that shows the possibility of implementing type inference in a ruby-like language rather than a new language. It can also be used by JRuby programmers to avoid going back to Java because of performance problems, or to implement some of the features of the JRuby itself, much like the slang of Squeak Smalltalk, a subset of the Smalltalk language that can easily be converted to C. The Rubinius program uses a similar approach called garnet (Infoq has cuby/garnet interviewed Evan Phoenix).
Now, what kind of code generation do you want to use for JRuby?