Aug 25, 2008

JRuby

Today I've been messing around with JRuby. I meant to check it out a while back, but have been procrastinating, and finally have gotten to it.
For those of you who don't know, JRuby is an implementation of Ruby in the Java Virtual Machine. It can access all the Java core library classes, which is pretty damn sweet.

Here's my setup:
Ubuntu 8.04 64-bit
Athlon X2 6400+
Ruby 1.8.6
JRuby 1.1.4
OpenJDK 6b11

So you may think, "oh, it has access to the Java libraries. So what? Ruby has tons of libraries." Well, Java has more, so it's always beneficial to have access to that.

Here is my main reason though. I made a little script that looks like this:
require 'benchmark'

def pythag(n)
result = []
(2..n).each do |c|
(1..c).each do |b|
a = Math.sqrt(c*c - b*b)
result << [a.to_i, b, c] if a.to_i == a
end
end
result
end

puts Benchmark.measure { pythag(5000); pythag(5000) }
Actually I didn't write it, I stole it off a comment from this article here. But anyway, check this out:
rob@alien:~/Programming/jruby$ ruby benchmark.rb 
40.750000 2.550000 43.300000 ( 43.440552)
rob@alien:~/Programming/jruby$ jruby benchmark.rb
14.920000 0.000000 14.920000 ( 14.919958)
I almost fell out of my chair. JRuby is over twice as fast! I was expecting that they'd be about the same, or JRuby might be a bit faster, but no. Over twice as fast. Damn.

You may notice I called pythag twice. I did this to see if it would make a difference because of JIT-compiling, and it doesn't seem to. Here's the output if I just call it once:
rob@alien:~/Programming/jruby$ ruby benchmark.rb 
19.560000 1.170000 20.730000 ( 20.934664)
rob@alien:~/Programming/jruby$ jruby benchmark.rb
7.999000 0.000000 7.999000 ( 7.998930)
Pretty much half as long.

I'm hoping to start running some other benchmarks. Here's another one I tried:
require 'benchmark'

def load(file)
words = {}
File.open(file, "r") do |f|
f.each_line do |l|
l = l.split(/[\s,\.!\?\"\';:]+/)
l.each do |w|
w = w.downcase
words[w] = (words[w] ? words[w] + 1 : 1)
end
end
end
words
end

puts Benchmark.measure {
words = load("kingJamesBible.txt")

words = words.to_a.sort { |a, b| b[1] <=> a[1] }

for i in 0..10
#puts "%s: %d" % [ words[i][0], words[i][1] ]
end
}
And the results:
rob@alien:~/Programming/jruby$ ruby benchmark2.rb 
2.370000 0.120000 2.490000 ( 2.487271)
rob@alien:~/Programming/jruby$ jruby benchmark2.rb
2.570000 0.000000 2.570000 ( 2.570358)
This time JRuby took longer. Not sure what to think here! Maybe it's fast in certain situations but not so fast in others.

Did you know the words "shall" and "unto" appear more often than "for" or "I"? Weird.

2 comments:

Guillaume Theoret said...

I think the only other platform I'm going to try is MagLev if it turns out to not be vaporware.

Rob Britton said...

Nice, it looks pretty good. It seems fairly high level, I'm not sure what I'd really think of it until I actually got it into production.