Well, how slow? During my quest to find out, I collected some interesting data, and even more importantly put JRuby and MRI Ruby face to face.
Disclaimer: the benchmarks were not done on a well isolated and specially configured test harness, but I did my best to gather data with informational value. All the components were used with OOB settings.
Setup
- ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0] + Mongrel Web Server 1.1.4
- jruby 1.1.6 (ruby 1.8.6 patchlevel 114) (2008-12-17 rev 8388) [x86_64-java] + GlassFish gem version: 0.9.2
- common backend: mysql5 5.0.75 Source distribution (InnoDB table engine, Rails pool set to 30)
Benchmarks
I used an excellent high quality benchmarking framework Faban for my tests. I was lazy, so I only used fhb (very similar to ab, but without its flaws) to invoke simple benchmarks:- simple request benchmark: bin/fhb -r 60/120/5 -c 10 http://localhost:3000/buckets/1
- component request benchmark: bin/fhb -r 60/120/5 -c 10 http://localhost:3000/bucket1/object1
Results
ruby 1.8.6 + mongrel --------------------------------- simple action + single-threaded: ops/sec: 210.900 % errors: 0.0 avg. time: 0.047 max time: 0.382 90th %: 0.095 simple action + multi-threaded: ops/sec: 226.483 % errors: 0.0 avg. time: 0.044 max time: 0.180 90th %: 0.095 component action + single-threaded: ops/sec: 132.950 % errors: 0.0 avg. time: 0.075 max time: 0.214 90th %: 0.130 component action + multi-threaded: ops/sec: 131.775 % errors: 0.0 avg. time: 0.076 max time: 0.279 90th %: 0.125 jruby 1.2.6 + glassfish gem 0.9.2 ---------------------------------- simple action + single-threaded: ops/sec: 141.417 % errors: 0.0 avg. time: 0.070 max time: 0.259 90th %: 0.115 simple action + multi-threaded: ops/sec: 247.333 % errors: 0.0 avg. time: 0.040 max time: 0.318 90th %: 0.065 component action + single-threaded: ops/sec: 107.858 % errors: 0.0 avg. time: 0.092 max time: 0.595 90th %: 0.145 component action + multi-threaded: ops/sec: 179.042 % errors: 0.0 avg. time: 0.055 max time: 0.357 90th %: 0.085
Platform/Action | Simple | +/- | Component | +/- |
---|---|---|---|---|
Ruby ST | 210ops | 0% | 132ops | 0% |
Ruby MT | 226ops | 7.62% | 131ops | -0.76% |
JRuby ST | 141ops | -32.86% | 107ops | -18.94% |
JRuby MT | 247ops | 17.62% | 179ops | 35.61% |
Conclusion
From my tests it appears that MRI is faster in single threaded mode, but JRuby makes up for the loss big time in the multi-threaded tests. It's also interesting to see that the multi-threaded mode gives MRI(green threads) a performance boost, but it's nowhere close to the boost that JRuby(native threads) can squeeze out from using multiple threads.During the tests I noticed that rails was reporting more times spent in the db when using JRuby (2-80ms) compared to MRI (1-3ms). I don't know how reliable this data is but I wonder if this is the bottleneck that is holding JRuby back in the single threaded mode.
2 comments:
I benchmarked jruby-1.1.6, glassfish3 and rails-2.2 running on threadsafe mode.
The page I tested had several db lookups (perhaps 20), so it was rather rough on the implementation. I noticed that jruby+glassfish with several threads (i.e. stressing the CPU at 400%) was as fast as ruby+mongrel in single thread (i.e. stressing the CPU at 100%). So, jruby+glassfish was 4 times slower than ruby+mongrel. The DB used was mysql, and on jruby, I used the jdbcmysql adapter.
Was the number of requests per second the same in both cases? The difference in cpu usage only shows that jruby can use all four cpu cores you have, while c-ruby can use only one.
Post a Comment