Art Of Programming

musings by Dmytrii Nagirniak

Issues Switching to JRuby From MRI 1.9

UDPATE: The reason for switching to JRuby the native neo4j API. Have to use REST API with MRI.

This is just a quick recap of what issues I have had trying to switch existing app from MRI Ruby (1.9.3) to JRuby (1.6.4).

Unfortunately I stepped back and didn’t want to spend more time as it felt an unbreakable chain of issues. Resolving one, you think “huh, awesome”. But very soon you hit the next.
And I couldn’t see it stopping.

But PLEASE bear in mind that I only spent a couple of hours on that. With a little bit more persistence, you may be able to the end of the tunnel.

The overall impression is that it is not a big deal really. The problems arise when trying to use other libraries. And unfortunately, not all of the gems care deep enough to support JRuby. And this is the biggest issue in my opinion, there are very little issues with JRuby itself. The transition (from the syntax perspective) was extremely easy.

The application is pretty standard Rails 3.1 app that uses gems like Dragonfly, inherited_resources, cancan, paper_trail, Authlogic, CoffeeScript, Haml, Sass, Formtastic etc. For testing - things like rspec-rails, cucumber-rails, capybara-webkit, guard (rspec and cucumber), database_cleaner etc.

So here is a quick list of the things that I faced on my way.

Before everything else I enabled support for 1.9 syntax in JRuby (export JRUBY_OPTS=–1.9).

It all first started with the weird issue where the wrong arguments were passed to RSpec shared example.
Unfortunately I did not figure out why it happened and just patched it as you can see in the comments there.



After fixing this issue I had another one related to database_cleaner. So I ended up with a pull request that worked for me.

The other issue was a huge stack trace. I scrolled 3 pages in the terminal to get to the top. Most of that stack trace is deep inside Java. Additionally I got wrong line number on exception. This “features/step_definitions/company_steps.rb:234” makes me thing that the exception is at line 234. But that file only had 49 lines of code. Now, go figure.

Going on… SimpleCov gem didn’t work out of the box and gave the warning that I need to enable debugging. That’s fine and understandable. But after half an hour of debugging of unrelated exception, it turned out that SimpleCove threw an exception because of that. So had to go and explicitly disable it.

Then I managed to run all of my specs. But I was pretty surprised how slow it was:

# rvm use 1.9.3
# time rspec # real=14s, rspec time ~ 12s

# rvm use jruby
# time rspec # real=52s, rspec time ~ 30s


But this is expected as JRuby doesn’t have enough time to optimise here. It should be much better in production. But it will be also shit slow after deployment.
Ok. That’s fine. I can trust it’s fast.

Then I tried running the cucumber specs and had to file the issue to support new Ruby 1.9.3 syntax (a = b = f 1). Not a big deal, easily fixed with parens: a = b = f(1).

Next and the final issue - I could not run the headless cucumber specs (capybara-webkit). It just got stuck (no CPU used) and feels like there is a dead-lock or something similar.

I couldn’t see way of fixing it easily and decided that for now I am done with it. So going back to Ruby 1.9.3.


To summarise, I did not feel like it’s a problem to switch to JRuby. But it’s really a big deal to actually use it due to the number of C extensions that JRuby doesn’t really support.

Again, to emphasise, there is nothing horribly wrong with JRuby and it seems to be pretty good. But the real showstoppers are the C extensions.

Comments

Dmytrii Nagirniak
Totally with you on this. But real world seems to be a bit different :)
Postmodern
Yet another reason to avoid C-extensions. When selecting dependencies for a new project, I prefer to select pure-Ruby libraries or FFI bindings (https://github.com/ffi/ffi#readme). Pure-Ruby libraries should be faster on Rubinius/JRuby. FFI bindings work perfectly on both MRI and JRuby.

If developers want faster Ruby code, they should help make MRI faster (or switch to Rubinius/JRuby), instead of writing more code in C.

Comments