Alexander Dymo

This is the second post of my pre-RailsConf series of blog posts on Rails application performance optimization. I'll be presenting at RailsConf about this and many other aspects of performance optimization on May 6th, so you're welcome to join me at RailsConf and please watch for more performance-related articles in this blog.

See also the previous article in this series on improving Date class performance.

We saw lots of synthetic benchmarks proving that alternative ruby implementations (namely the only two finished ones - JRuby and Ruby 1.9) are faster than good old 1.8 aka MRI. But nobody so far ported the production application to prove they are faster in the real world conditions. We did.

"Ruby 1.9 is 2x faster than 1.8. But the real world improvements are even better." "Ruby 1.9 is 2x faster than 1.8. But the real world improvements are even better."

We ported Acunote - our online enterprise project management and Scrum software to both JRuby and Ruby 1.9 and ran our set of performance benchmarks. We have 30 benchmarks that check the server response time for most typical user requests. We use those benchmarks to check for performance regressions, and this time we used them to check the Acunote's performance with alternative rubys.

There're four common request types for Acunote, ones that primarily involve date/time operations, rendering, numerical calculations and ActiveRecord/database operations.

Here are the timings for four requests, one for each type:

Acunote Benchmark Request Time, sec Improvement 1.8.6 JRuby 1.2.0 1.9.1 JRuby 1.9.1 Date/Time Intensive 1.23 0.58 0.53 2.1x 2.3x Rendering Intensive 0.61 0.44 0.30 1.4x 2.0x Calculations Intensive 2.57 1.79 1.33 1.4x 1.9x Database Intensive 5.58 4.63 3.29 1.2x 1.7x

Here are those timings expanded with rendering and database time:

Acunote Benchmark Request Time / Rendering Time / DB Time, msec 1.8.6 JRuby 1.2.0 1.9.1 Date/Time Intensive 1230 / 0 / 65 580 / 1 / 45 530 / 1 / 37 Rendering Intensive 610 / 328 / 33 440 / 273 / 45 300 / 197 / 37 Calculations Intensive 2570 / 380 / 38 1790 / 215 / 54 1330 / 204 / 39 Database Intensive 5580 / 529 / 700 4630 / 209 / 1321 3290 / 221 / 685

As you can see from the table, Ruby 1.9 is 2x faster than 1.8. But the real world improvements are even better. Ruby 1.9 eliminates performance bottlenecks that were present in 1.8, e.g. Date class, numerical and string computations, template rendering. It lets us write more complex systems in Ruby than were ever possible before. In the immortal words of Avi Bryant, it lets us add a whole 'nother level of turtles.

The performance improvement from JRuby is not as substantial, but it's still 1.5x faster. One of the reasons for JRuby being slower than 1.9 is PostgreSQL JDBC driver and not-working "fast" mode.

Want to know why 1.9 and JRuby are so much faster? Are there any other improvements and regressions with alternative Ruby's? What happened to the garbage collection performance? To learn the answers, join me at my RailsConf session or watch for the more detailed analysis in this blog.