The Great Ruby Shootout (July 2010)
programmingzen.com
programmingzen.com
For the base perf numbers, I'm not surprised. We've known that we're roughly on par with 1.9.2 for some time, and many of the benchmarks in question have started to reach a point of irreducible complexity (e.g. you can only slice and dice strings so fast). It's good to see JRuby remains at or near the front of the pack as far as performance, especially considering we've made no major performance-related changes in almost two years.
The Linux versus Windows numbers are a bit surprising to me. If I were to make a guess, I'd guess that the JVMs used were not identical (perhaps like Isaac Gouy mentions, one platform was 64-bit and the other wasn't) or some other detail altered the performance characteristics of the test. But the performance drop does seem to be in line with other implementations, so perhaps Windows really does suck and there's not much we can do about it.
On the memory issue, I have a few recommendations.
JRuby by default allows the JVM to use up to a 512MB heap (the default is usually 32-64MB, which is rarely enough for most nontrivial apps). The JVM likes to use as much memory as you're willing to give it, to keep GC times low (nearly free) and to give it lots of room to breathe. Almost all these benchmarks could run in far less memory (maybe 1/5 as much or lower) if the JVM were choked down to that level. So it's not surprising to me that the memory sizes for these very object and CPU-intensive benchmarks start to approach that 512MB limit; the JVM is just stretching its legs.
Expect to see a lot more performance work coming in JRuby 1.6. I've blogged about it here: http://blog.headius.com/2010/05/kicking-jruby-performance-up...
Also expect to see more work on picking a "winner" as far as lightweight servers go. Something that works as seamlessly as Passenger could be the "last mile" we need to get folks to make a move.
And watch our two Ruby Summer of Code projects: Ruboto, bringing JRuby to Android; and C extension support.
We're working very hard to bring JRuby to everyone and everyone to JRuby. The reasons not to use JRuby are rapidly disappearing.
The same identical version was used: Java HotSpot(TM) 64-Bit Server VM 1.6.0_20.
> But the performance drop does seem to be in line with other implementations, so perhaps Windows really does suck and there's not much we can do about it.
The leading theory. ;-)
Internally it uses Jetty's event-driven I/O, so performance is on a par with Thin and Passenger, at least on my MacBook.
I'm a bit pressed for time at the moment, so if anybody wants to add in the cometd servlet (it's in the repos) and write a tutorial, that'd be awesome, and if not, I'll get to it in a few weeks.
3 years ago, Ruby implementation problems became the hot topic at Ruby conferences. Ruby was a beautiful language with an ugly implementation. It's great to see that the community has executed on this concern.
I think once JRuby has stabilized the native gem support and has some sort of Passenger-like deployment option (Glassfish and Warbler isn't quite there yet), we'll see some big players built on MRI start to move their Web applications to the platform.
Most current startup slowness is due to the JVM itself running slow during the first few seconds of execution. Ruby scripts execute as they boot, which means we have to parse and run them. But until the JVM's been up for a little while, nothing in JRuby itself has even JITted to native code...and interpreted JVM bytecode runs even slower than Ruby on most of my tests.
The other complicating factor is the fact that Ruby applications run so much code on boot. RubyGems, for example, degrades startup time O(n) based on how many gems you have installed. Hacks like faster_rubygems (gem install faster_rubygems) help, but changes are needed in RubyGems proper.
In any case, we feel the startup pain too. I've blogged a few tips about startup time here: http://blog.headius.com/2010/03/jruby-startup-time-tips.html, and I've described some of the challenges here: http://blog.headius.com/2010/06/my-short-list-of-key-missing...
We're working on it...we really are. We're just fighting against a decade of JVM folks who never run command-line tools.
Sure, it takes longer to start up, but we're talking a few seconds here, which is nothing for a long-running webapp. Plus, the JVM is rock-solid, has very predictable memory usage, and also has tons of monitoring infrastructure to bring to bear against problems.
Yeah, I'm a fan.
I've read that JRuby memory usage scales better than MRI though, so you pay a higher cost upfront but can actually accommodate more workers on the same hardware. I haven't gotten far enough in my exploration of JRuby to see if this is the case in my own apps.
Hats off to all the devs working on bringing us a better Ruby runtime. I realize it's a lot of work.
I think having a Ruby toolbox instead of a single big hammer is a win for everybody.
Disclaimer: I haven't dug into this issue much, so its possible other factors are the cause...
http://java.sun.com/developer/technicalArticles/DynTypeLang/
But perhaps the most interesting aspect of any new major Java release is that they're usually 10-20% faster across the board, due to new and better optimizations. As the saying goes, if your Java app isn't fast enough, upgrade to a newer JVM.
I think invokedynamic combined with more runtime profile-driven optimizations in JRuby could easily double JRuby's Ruby-execution performance (or better), and in many cases reduce memory churn too. Lots of good things coming...it's nice to have an army of VM engineers on your side.
It's the other way around. Given the skewed nature of the data, the median is a better measure of the central tendency of the data set.
But note that I'm not plotting the median only. I use a box plot which gives you a much better statistical picture than using a simple median (or mean). Nevertheless, summarizing different benchmarks has its limitations and box plots give you a rough, general idea of what's going on.
The box plot is a good choice here. What I would like to see is a graph plotting time against {VM} x {benchmark size} to see how each platform scales within a benchmark.
With the data you've got, apart from confusing me a little by including the mean and median, you did a good job presenting it. I'd love to see why some platforms do so much well than others in some cases (except JRuby which everyone knows is a memory hog), but this seems way out of scope for this article. :)
At this point, we realize that sometimes you really do need native performance, and we're not taking any options off the table to get there.
Maybe I could tune software with profiling tools after the fact. But it feels like as soon as you start locking specific objects down it's a slippery slope.
I'm not very familiar with the depth you've gone to, but can a dynamic object have numeric features or be capable of substituting numeric handling for a limited time (virtual numerics) and then revert back to a sloppy untyped object?