This week I started migrating an internal application for MyJibe to JRuby 1.6 and was pleasantly surprised with the results. After seeing that others didn’t have the same positive experience as I did, I thought I would go into a little more detail about how we are using JRuby/Rails and the results we have seen.
You can use SOAP4R and WSSE (for basic ws-security), but they are both light on the SOAP/WS stack as a whole.
My life before MyJibe was almost all Web Services. SOAP everywhere and lots of Java, C++, C# and Visual Basic (yep, VB). The reality of the daily life of a technologist in large financial institutions is tons of Java/.Net/SOAP and software built with those tools (Oracle, Spring, Struts …..) This is both good and bad, but this is not a post on the virtues of Java vs Ruby vs .Net vs Python vs C++ (my native language)
Long story short, I know how to utilize Java’s support for SOAP and have found myself needing the same support for SOAP in Ruby and wanted to find a solution to link the two, so I chose JRuby (as it would be impossible to rewrite the volume of “Enterprisey” API’s for the financial industry on another “platform” …. for this context [impossible = improbable = unprofitable])
After recognizing that I could use jars with JRuby I decided to create a translation layer for any endpoint that we needed to integrate with that didn’t have native support for REST/JSON. Pretty straight forward.

A request comes in and is routed via Rails, the controller parses out the JSON request, the model performs any validation and uses Java’s extensive protocol support to call out to services that don’t speak a “native” JSON. (Services have different levels of configuration/structure which is typically setup during startup through an initializer)
The primary focus of my testing was request parsing/dispatching and connection overhead. Since the primary function of the JRuby/Rails application is to route requests and do very little in the execution chain my tests were specialized. When multiple endpoints are being accessed by multiple Rails servers simultaneously the dispatching and parsing routines are the primary controllable bottleneck because they are executed for every request. (Validation is important, but some services never use validation as they are either unidirectional requests or fail proof requests that queue background work for delayed execution)
(Note: After reading Jeff Dean’s post on lightweight Rails services we removed some of the Rails overhead for the service translator, which resulted in ~10% increase in request-response performance.)
(disclaimer ** we had no issues or perceived slowness with JRuby 1.5.6 before testing the upgrade and were happily surprised by the performance boost from JRuby 1.6 and Trinidad 1.0.5)
Since I was largely testing the “Time to Service-call” or “dispatching time” it was not necessary to call a web service for the test as the primary controllable overhead would be in dispatching/parsing requests. Although I will continue to investigate parsing times and service responses.
Tester.test

Tester.time

Using the ruby “Benchmark” library I ran this snippet of code against each server listening on a local port. (Tester is a Ruby Object that communicates to the the JSON service endpoint)

JRuby 1.5.6 with Trinidad 1.0.3


JRuby 1.6.0.RC1 with Trinidad 1.0.5


JRuby 1.6.0.RC1 with Trinidad 1.0.3

After seeing the changes from JRuby and Trinidad versions I decided to also check the Ruby MRI interpreters on my machine (1.8.7-p302 and 1.9.2-p136)
1.8.7-p302

1.9.2-p136

The difference between JRuby 1.5.6 and JRuby 1.6.0 is relatively small. 4-9 seconds over 3000 requests is not “significant” by my measure however, it does account for the 20-25% increase in performance across requests running through the JRuby 1.6.0 install in our testing environment. It has also set a new record for fastest full request cycle of our most complex remote calls (multi-key, session based SOAP calls), beating our former record by ~25%.
I was very surprised with the difference in speed between JRuby and Ruby 1.9.2. I assumed that they would perform in the same ballpark when it came to routing requests and basic responses. I still need to investigate further on why such an extreme difference, but it does show that if you are considering running a lightweight REST or Remote Invocation service you should entertain JRuby/Trinidad/Rails as the platform and framework of choice.
Design by Simon Fletcher. Powered by Tumblr.
© Copyright 2010