down the jruby rabbit hole
So recently at work we finally decided (after some prodding from me) to go with JRuby for a new production system.
I had no real experience with JRuby other than looking at some documentation and playing with it for five minutes, so here’s some JRuby-related topics I bumped into and I’ve been wanting to write about.
start-up time during development
Since the system hasn’t yet been deployed, I don’t have deployment stories to share, but for development I have some tips:
export JRUBY_OPTS='--dev'
-
Do define the magic
--dev
default option in your local development environment!With this flag active, JRuby optimizes for startup time, so your fast
rspec
cycles andpry
usage stops being painful.(Of course, do note that steady-state performance will drop, so don’t use this for long-running code.)
-
Use binaries directly (or with
jruby -S
) rather than withbundle exec
whenever possible. On my machine runningrspec
orjruby -S rspec
instead ofbundle exec rspec
slices start-up time in about half.
These tips are documented in the JRuby wiki but I can’t stress enough the difference they make between JRuby being painful and a pleasure to use during development.
Edit: I suggest also looking at the --binstubs
bundler option.
easy interop with java code
Don’t abuse it, but I must say it’s really easy to call Java code:
[1] pry(main)> require 'java' => false [2] pry(main)> l = java.util.ArrayList.new() => #<Java::JavaUtil::ArrayList:0x7c24b813> [3] pry(main)> l.add(:foo) => true [4] pry(main)> l.add(:bar) => true [5] pry(main)> l.to_string => "[foo, bar]"
bonus: warbler and the magical jar
While you can use bundler
and many of the same techniques and platforms you are used to with mri (such as the puma webserver), an interesting tool I’ve recently discovered that is also developed by the JRuby team is warbler
.
Warbler allows you to package a ruby application as a single jar or war file, that can be executed like any other java code standalone or (if applicable) on an application server. If needed, it can even bundle in a Java webserver that will call your ruby code.
Turning a simple ruby script into an inconspicuous jar is as simple as:
$ gem install warbler Fetching: jruby-jars-9.1.2.0.gem (100%) Successfully installed jruby-jars-9.1.2.0 Fetching: jruby-rack-1.1.20.gem (100%) Successfully installed jruby-rack-1.1.20 Fetching: rubyzip-1.2.0.gem (100%) Successfully installed rubyzip-1.2.0 Fetching: warbler-2.0.3.gem (100%) Successfully installed warbler-2.0.3 Parsing documentation for jruby-jars-9.1.2.0 Installing ri documentation for jruby-jars-9.1.2.0 Parsing documentation for jruby-rack-1.1.20 Installing ri documentation for jruby-rack-1.1.20 Parsing documentation for rubyzip-1.2.0 Installing ri documentation for rubyzip-1.2.0 Parsing documentation for warbler-2.0.3 Installing ri documentation for warbler-2.0.3 Done installing documentation for jruby-jars, jruby-rack, rubyzip, warbler after 1 seconds 4 gems installed $ cat bin/test.rb puts "hello, world!" $ cat config/warble.rb Warbler::Config.new do |config| config.features = %w(executable) config.jar_name = "test" end $ warble jar rm -f test.jar Creating test.jar $ java -jar test.jar hello, world!
And that’s all there is to it, and you now have a single jar that anyone will be able to easily run on their local machine.
Big kudos to the JRuby team for this one!
dealing with java jar dependencies
So one of my colleagues asked: what about jars? Do you have to break out maven
? How does that work?
The answer turns out to be no, you can just use jbundler
to do that work for you. It looks and feels like bundler, and you feed it with a Jarfile
and magic happens.
Of course, approach this with care, as when you start depending on Java code you cannot go back to MRI or other ruby implementations.
a shout out to jruby+truffle
I’m really looking forward to what I believe is the next big thing in the ruby implementation arena: JRuby+Truffle.
Its name can be somewhat misleading, as it’s a very different beast from vanilla JRuby. JRuby+Truffle instead uses a self-optimizing AST interpreter that basically teaches the JVM (via the truffle api and the graal compiler) how ruby works and how to optimize its execution.
The resulting benchmarks are looking very good, although a few sharp edges still stand before it can really be rolled out to production.
Chris Seaton, its creator, gave an awesome talk about it recently at VMSS16, which I really recommend watching:
P.s.: There are a lot of other great talks from that event, such as Cliff Click’s.
crystal, I am disappoint
A few months ago I was really getting interested in the Crystal programming language but after discovering that it doesn’t have multi-threading it became kind-of meh.
As a shared-memory concurrency junkie, it really seems weird to have a new language being created that doesn’t properly consider concurrency. Hopefully in the future this will be fixed, but until then, it seems like JRuby and Elixir are where the parallel party’s at!