Do you want to squeeze the most performance out of your Ruby scripts? If so, you might be interested in a little project called XRuby.
According to the website “in most benchmark tests, XRuby runs faster than Ruby 1.8.5″. Personally, I was a bit skeptical, and you may be too. So let’s explore this lofty claim further and see if we really can achieve better performance for my highly <snicker> complex Ruby scripts.
First, let me address what you are thinking… Does it run Rails apps? At the moment, no, but it has made great strides and will hopefully achieve that goal sometime in the future. Currently it is able to pass all tests found in the samples folder of the standard 1.8.5 installation. That’s pretty impressive. Now, I want to validate that performance claim. Here is the procedure to set up XRuby and run a Ruby-turned-Java example.
This article operates under the assumption that Java 6 SE has been installed. If you are running Ubuntu and don’t yet have Java 6 run the following command:
codenomad@sparta:~/$ sudo apt-get install sun-java6-jdk
Now, grab a copy of XRuby over at http://code.google.com/p/xruby/ and then do the following in your directory of choice. (My home folder is the default directory where the zipped file is located, and the current release is xruby-0.3.3a).
codenomad@sparta:~$ mkdir xruby codenomad@sparta:~$ cd xruby/ codenomad@sparta:~$ unzip ../xruby-0.3.3a-src.zip
On to the build process.
Before you can build XRuby, you need to set the environment variable JAVA_HOME to your JVM installation and give the build script execute permissions.
For Ubuntu, there is a symbolic link that points to the latest Java installation under /usr/lib/jvm. Below is how you would set that variable and build XRuby.
TIP: Ubuntu does provide a command line utility to switch your Java implementation quickly called ‘update-alternatives‘ This utility can be used to update symlinks for commonly used executable names like ‘java’ on your Debian or Ubuntu install quickly.
codenomad@sparta:~/xruby$ export JAVA_HOME=/usr/lib/jvm/java-6-sun codenomad@sparta:~/xruby$ chmod +x build.sh codenomad@sparta:~/xruby$ ./build.sh
After this you should have an xruby-0.3.3.jar that will be used to compile Ruby code. Before I go any further, I’m going to move the xruby-0.3.3.jar to a more convenient location inside my ~/Code folder.
codenomad@sparta:~/xruby$ mv xruby-0.3.3.jar /home/codenomad/Code/ codenomad@sparta:~/xruby$ cd /home/codenomad/Code/
Now, let’s start writing some Ruby code using a simple “hello world” script. Create a file called hello.rb and add the following lines.
#!/usr/bin/ruby puts "Hello World"
Lets make the Ruby script executable, and test it out:
codenomad@sparta:~/Code$ chmod +x hello.rb codenomad@sparta:~/Code$ ./hello.rb Hello World codenomad@sparta:~/Code$
Cool, we have a working Ruby script. Now lets Java-fy it!
codenomad@sparta:~/Code$ java -jar xruby-0.3.3.jar -c hello.rb Generated hello.jar codenomad@sparta:~/Code$
It took me a little bit to figure out how to invoke my new found bytecode, but I’ve found that the easiest way is to put the xruby JAR and the hello.jar in the classpath and execute the main class stored inside the hello.jar. You can inspect the compiled JAR if you expand it, but I’ll save you the trouble and tell you that the main class is located at xruby.hello.main. So, let’s be sure our Ruby script works:
codenomad@sparta:~/Code$ java -cp xruby-0.3.3.jar:hello.jar xruby.hello.main Hello World codenomad@sparta:~/Code$
As you will see, it works as advertised but it really doesn’t show us a whole lot. Let’s try something that spins the CPU a bit more with a simple Fibonacci number calculator.
I included a timer in the code to keep track of any performance increase using XRuby. So, first create a file called fib.rb and add the following lines:
#!/usr/bin/ruby
require 'time'
puts "starting fibonacci"
def fib(num)
if(num < 2)
return 1
else
return fib(num-1) + fib(num-2)
end
end
if ARGV[0] != nil
if (ARGV[0].to_i >= 35)
puts "This might take a bit...."
end
start = Time.now
puts fib(ARGV[0].to_i)
stop = Time.now - start
puts "Finding the fib of #{ARGV[0]} took:"
puts stop
puts "seconds"
end
Let’s make the new file executable and run it just as a sanity check:
codenomad@sparta:~/Code$ chmod +x fib.rb codenomad@sparta:~/Code$ ./fib.rb 20 starting fibonacci 10946 Finding the fib of 20 took: 0.135409 seconds codenomad@sparta:~/Code$
Now let’s compile it to Java bytecode, and execute the script using XRuby.
codenomad@sparta:~/Code$ java -jar xruby-0.3.3.jar -c fib.rb Generated fib.jar codenomad@sparta:~/Code$ java -cp xruby-0.3.3.jar:fib.jar xruby.fib.main 20 starting fibonacci 10946 Finding the fib of 20 took: 0.083 seconds codenomad@sparta:~/Code$
There is at least a noticeable speed up doing this. To really see a speed increase let’s try a bigger number like 35…
codenomad@sparta:~/Code$ ./fib.rb 35 starting fibonacci This might take a bit.... 14930352 Finding the fib of 35 took: 187.172469 seconds codenomad@sparta:~/Code$
Wow, that’s a pretty long run for such a little number, let’s try the bytecode run:
codenomad@sparta:~/Code$ java -cp xruby-0.3.3.jar:fib.jar xruby.fib.main 35 starting fibonacci This might take a bit.... 14930352 Finding the fib of 35 took: 42.199 codenomad@sparta:~/Code$
I hope any questions about a performance increase were put to rest. The XRuby invocation of this simple Fibonacci script was 4.435 times faster than the native Ruby script! Granted you might not be able to convert every Ruby script that exists out in the wild, but if you write a script using the base libraries you can benefit quite a bit just by converting to Java bytecode.
Despite the lack of Rails support, the performance gain alone is enough to check this project out. If you do, let us know!



(Rating: 4 stars, Click to rate this article!)














Leave a Reply