Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Discussion of JVM performance from JRuby/Clojure creators (groups.google.com)
41 points by bgray on Nov 20, 2009 | hide | past | favorite | 13 comments


I have been curious about JRuby for a long time, and relatively recently I got a chance to work on a JRuby-powered Rails application that hits a database, uses external Java APIs and serves pages.

The experience has been miserable: the "warm-up problem" is so pronounced that development reminds me of my C++ days when I had to compile my code. Rake tasks are slow as hell. Running unit tests has been so painful that we hacked Rails to run tests via Web interface. Memory consumption is through the roof: JVM-based Ruby eats (or should I say wastes?) about 2-3x times more RAM that RubyEE 1.8.6

You keep hearing RAM is cheap, but for small startups no it isn't - just look at EC2/SliceHost/Linode prices, and 1GB instances aren't going to cut it if you're running this pig (JVM) doing anything non-trivial.

Moreover, accessing Java classes from JRuby isn't nearly as smooth as using something like Closure. Ruby strings aren't Java strings and it applies to arrays, hash tables, everything. Even importing JARs isn't that trivial. Moreover, your Ruby code which consumes Java libs looks more or less like Java in a Halloween costume. NOT FUN.

The bottom line: yes, Rails on JRuby is about twice as fast (in our application) but you take a shocking hit to your workflow by the startup lag and you pay with an increased RAM wastage by JVM when you deploy.

Next time I am needing some Java libraries in a Rails app, I am hosting an instance of Tomcat and exposing that library via a simple REST service using plain Java.


My current project is JRuby on Rails, so I wanted to inject my few cents, and also to ask what your long-term experiences with the platform were.

Rake tasks are definitely slow; you have to wait a few seconds for them to complete, which overall sucks. A lot. If anything, this is the one thing that has pushed me to thinking about using MRI again. Nailgun is supposed to help a lot here, and since JRuby 1.4.0 was recently released, I'll be giving NG a go and seeing what the improvement is for common rake tasks.

RAM hasn't been a big problem for me. The JVM does use more RAM than MRI, but it also seems to do a better job of managing it. I've never had an out-of-memory error, and the nastiest benchmarks I could throw against my code (a few hours' worth of solid requests) don't jack the JVM above around 200M of RAM, and that's with an embedded Solr server for indexing/searching. BUT... we haven't done a fully public beta yet, just the 'friends and family' version. So I could be talking out of the wrong orifice here.

You get real threading, which makes setting up a job scheduler a lot easier, and lets you run a multithreaded Rails server.

The performance is quite good when compared to the 1.8.7 MRI.

Accessing Java classes isn't as nice as Closure/Groovy, but that's to be expected. Closure and Groovy were designed from the ground up to use Java classes as their foundation, and Ruby... wasn't. Even so, JRuby does a decent job of autoboxing most of the time with strings and arrays, and I've had only a few speedbumps when using Java classes in JRuby.

Loading JARs seems to work fine with 'require' for me; what problems have you run into?

What is the long-term memory use for your application like; e.g., does it grow hugely over time, or remain relatively stable after the JVM warmup?

What JVM/JRuby are you using?

Other than startup slowness, what other issues have been problems for you?


Our application is a data cruncher, it's not a public web site, and our controllers/views are just a GUI to control/monitor the process.

Memory usage shuts up to 700-800MB per Rails instance but it stays there regardless of how many documents we put through the pipeline.

Also our migrations stopped working in test environments - JDBC db adapter would "reset" itself back to mysql MRI gem ignoring database.yml. On CentOS it would happen with all environments, not just test. We were never able to figure out where/how this happens due to extremely dynamic/"magic" nature of AR and Ruby in general, so we're using MRI just to run migrations and we moved to Ubuntu in production to keep JRuby/JDBC happy

But my biggest objection to using JRuby in the future is that it's easier to use Java for accessing Java libraries, i.e. using JRuby simply because you need some Java-based OCR package is simply not worth it - my advice would be to use Java to access that API and then interop with MRI somehow, I would do it via HTTP-based REST API between Rails/MRI process and Tomcat-hosted JVM.


You can limit the JVM heap size.


As a counterpoint, not every Ruby app is a Rails app. I've been using JRuby more and more lately for various text analysis projects. Calculating the mutual information over a huge set of tokens, for instance, was roughly 10 times faster in JRuby... And of course didn't suffer from the Unicode issues I was running into with Ruby (1.8). Regardless of whether or not it's suitable for Rails, it's absolutely suitable for other projects.


"As a counterpoint, not every Ruby app is a Rails app."

Quite true. I have a commercial desktop JRuby app,

But I've been running a production JRuby Ramaze app for about a year now as well (in support of that desktop app). It just works. Memory is not an issue.

It may be a matter of how various libraries behave, and specific demands of different apps, but I've not seen a reason to think JRuby is unsuitable for Web apps.


When I worked on a sizable JRuby/Rails codebase, our team had a hybrid approach: ephemeral jobs (rake tasks, migrations, autospec) all ran under MRI, while long-lived processes (app servers, CI/acceptance test runs) ran in JRuby. That gave us the best of both worlds: quick startup in cases where total runtime was an issue, and better throughput (and more predictable memory usage) for CPU-heavy workloads.

In my experience, MRI/REE fits into smaller RAM footprints only in cases where either you start up and shut down runtimes relatively regularly, or you can monitor for runaway leaks and terminate bloated processes.

I do agree that switching to a different runtime just to get access to a few libraries is probably the wrong approach, however. The big wins in using JRuby are, to me, twofold: a nice performance boost for general application code, and the availability of robust, battle-tested application servers. Mongrel, Unicorn, and Passenger are fine if you're willing to live on the edge, but if you have a more conservative ops team, or simply don't want to both with rolling your own monitoring and deployment stack, being able to drop a Rails app onto Tomcat or Glassfish as a single WAR file is pretty damn nice.


are you using the 32 bit or 64 bit jvm? The 64 bit doesn't have the client mode so it's going to be a lot slower at startup.


Awesome tip, thanks! We're 64 bit.


i hear you about the ram. i routinely get Jruby to crash with 'out of memory' errors even with min and max heap set to huge sizes, when YARV doesn't break a sweat.

Edit: I'll add that I'm not talking about rails, I use ruby for heavy data crunching. For general use jruby is great and I love that threads truly run in parallel.


> Running unit tests has been so painful that we hacked Rails to run tests via Web interface.

If that's because of the warm-up problem, Groovy is much better since it doesn't start a new JVM for each test.

> Moreover, accessing Java classes from JRuby isn't nearly as smooth as using something like Closure. Ruby strings aren't Java strings and it applies to arrays, hash tables, everything.

With Groovy, it's about as seamless as you're going to get. That was very much a design goal of Groovy.

The down side is, if you already know Rails, you have to learn half a language (Groovy borrows a lot from Ruby, so you only have to learn the deltas.) And of course you can't use Ruby packages. But you do get all Java libraries for free.


I started my current project in Grails, and switched back to Rails, because debugging was a nightmare. Massive stack traces (multiple hundreds of lines) due to reflection, and some really irritating typecasting nightmares due to the String/GString difference. The long-running memory leaks were the sort of things the Vikings wrote poetry about, because even Beowulf couldn't smite them.

Not to mention some massive showstopper bugs in Grails, things like 'logging doesn't work, and yes, we know.'

Also, if you want to 'break out of the box' in Grails, and are not a really seasoned Spring/Hibernate developer, good luck.

Groovy is a nifty language, and I like the idea of Grails. It's a great tool if you're already an experienced Java/Spring/Hibernate developer, but it isn't really a Rails replacement.


This is something that might be a good candidate for openjdk and/or icedtea. The only problem is the build seems to be regularly broken in the repository. - Andrew Oliver

I'm surprised that a project that large doesn't use something like tinderbox or cruise control.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: