Tuesday, December 9, 2008

New Ruby Shootout 12/08

Antonio Cangiano has released another Ruby Shootout which are always fun to check out.  Looks like Ruby 1.9 is leading the pack with JRuby 1.1.6RC1 close behind.  Some of the JRuby tests failed which I'm sure pissed Charlie off!

Friday, December 5, 2008

JRuby vs. Java speed (re: Stochastic Simulation with SSJ)

Just read Ali Rizvi's blog post about "JRuby: Stochastic Simulation with SSJ" and decided to take a look at the implementation real quick... of course the Java version will be much faster, but the numbers given seemed a little strange.  After setting up the environment and running the tests, I saw the major slowdown as expected, then I decided to take a look at the Ruby code to see if I could speed things up a little.  This was done rather quickly, if you have better result... please share!

First, the Java version:
real    0m7.960s
user 0m7.839s
sys 0m0.056s

The JRuby version took too long to run (I'm pressed for time) so I added a few options to the runtime:
[sourcecode language="css"]
jruby -J-Djruby.compile.fastest=true --server collision.rb
real 3m55.834s
user 3m53.684s
sys 0m2.355s
[/sourcecode]

Not as bad as reported by the blog ref'd above... but still pretty bad. I had a hunch the loops were what was killing the time and made the following changes to the collision.rb file:
[sourcecode language="ruby"]
@k.times { |i| @used[i] = false}
changed to:
@used.fill(false)
[/sourcecode]

That brought the time down a bit:

[sourcecode language="css"]
real 1m1.430s
user 1m1.344s
sys 0m0.538s
[/sourcecode]

It would seem loops are a sore spot. (kinda expected? the loop for setting happens in the Java impl) Decided to make one last change to see what happened. I condensed the "generate_c" method back into "simulate_runs" method to get the loops in one place. Some (not much) benefit was shown in my tests:

[sourcecode language="css"]
real 0m59.081s
user 0m59.027s
sys 0m0.502s
[/sourcecode]

CONCLUSION: Yes, straight java is faster. Yes, there are ways to tune your Ruby to make things a bit more efficient. Yes, I'm sure there are other ways to make this run faster. I think prototyping this sort of thing in JRuby is just fine... then when you need more perf (if this stuff will be called from say a JRuby on Rails app) you can code it up in Java (Collision.java) and just call that from JRuby layer.

Here is the final collision.rb I ended up with :
[sourcecode language="ruby"]
require 'java'
require 'ssj.jar'

import 'umontreal.iro.lecuyer.rng.RandomStream'
import 'umontreal.iro.lecuyer.stat.Tally'
import 'umontreal.iro.lecuyer.rng.MRG32k3a'

class Collision
def initialize(k, m)
@k = k
@m = m
@lambda = m * m / (2.0 * k)
@used = Array.new(k, false)
end

def simulate_runs(n, stream, stat_c)
stat_c.init
n.times do
c = 0
@used.fill(false)
@m.times do
loc = stream.nextInt(0, @k-1)
if @used[loc]
c += 1
else
@used[loc] = true
end
end
stat_c.add(c)
end
stat_c.setConfidenceIntervalStudent()
puts stat_c.report(0.95, 3)
puts " Theoretical mean: #{@lambda} "
end

def self.run
stat_c = Tally.new("Statistics on collision")
col = Collision.new(10000,500)
col.simulate_runs(100000, MRG32k3a.new, stat_c)
end

end

Collision.run
[/sourcecode]

Thursday, December 4, 2008

JRuby getting lots of attention lately

Of course while I'm away, toiling on projects using Spring/Hibernate, JBoss/EJB3/GWT things with the JRuby world get really exciting.  New versions of JRuby are rolling out everytime you turn around and the gems and projects that run on jruby are getting refreshed daily it seems.  Here are just some of the highlights I've seen fly by...

Hopefully I'll get some time of the holidays to dust off some of my (now old) projects and give them a whirl with all the new hotness... I'd love to do some more benchmarks and see if the thread-safety of Rails does anything to improve things on jruby outright.  Of course, I'll post results if I can get around to it.

For a sort of realtime look at what folks are doing with jruby: