15 May 2012
JRuby is awesome. The JVM’s startup time is not:
$ rvm use 1.9.3
Using /Users/michaelfairley/.rvm/gems/ruby-1.9.3-p125
$ time ruby -e "puts 'Hello'"
Hello
real 0m0.077s
user 0m0.031s
sys 0m0.013s
$ rvm use jruby
Using /Users/michaelfairley/.rvm/gems/jruby-1.6.7
$ time ruby -e "puts 'Hello'"
Hello
real 0m1.955s
user 0m1.268s
sys 0m0.212s
This makes doing TDD in JRuby more painful than it ought to be.
Luckily, JRuby has built in support for Nailgun, which can prevent the need for starting up a new JVM each time we want to run Ruby, making things a brazilian times faster.
Using Nailgun is simple. First, start up the Nailgun server:
ruby --ng-server
And then pass --ng
to ruby whenever you use it:
$ time ruby --ng -e "puts 'Hello'"
Hello
real 0m0.376s
user 0m0.001s
sys 0m0.004s
Much better.
Unfortunately, a teensy bit of monkey patching is required to get Nailgun playing nicely with autotest.
Dump this anywhere in your .autotest file:
# From https://github.com/rspec/rspec-core/blob/master/lib/autotest/rspec2.rb,
# but with "--ng" added.
class Autotest::Rspec2 < Autotest
def make_test_cmd(files_to_test)
files_to_test.empty? ? '' :
"#{prefix}#{ruby}#{suffix} --ng -S '#{RSPEC_EXECUTABLE}' --tty \
#{normalize(files_to_test).keys.flatten.map { |f| "'#{f}'"}.join(' ')}"
end
end
And then run autotest with Nailgun:
ruby --ng -S autotest
Boom. Now you have a subsecond test cycle in JRuby.