The startup time for a JRuby application comes down to four things: the startup time of the JVM, the loading of the JRuby runtime, and the loading of libraries, and finally the loading of the application code. The JVM is actually not that slow to start, and JRuby starts executing Ruby code pretty quickly, but due to a lot of factors it is not anywhere near as fast as MRI at loading and compiling Ruby code.
The overwhelming majority of JRuby startup time is unfortunately loading the JRuby core, the core libraries, the standard library, and your application code. Looking for files on disk and sometimes in JAR files, reading hundreds if not thousands of files, handling lots of exceptions that libraries generate during loading (try running with -Xlog.exceptions=true -Xlog.backtraces=true too see them all), it’s a lot of work.
Is it worth it? It’s definitely a pain waiting those seconds (though it’s not two minutes anymore) for the tests to run, for sure – and I have still not found anything that helps, Nailgun, Drip, I don’t remember all the preloading that I’ve seen over the years, they either don’t work very well, or they don’t matter because loading all that code is what takes the majority of the time.
I tried running the unit tests for an application (not Rails, just plain JRuby) and they run in 25s, (RSpec reports that “files took 10s to load”, but I’m not sure how it measures that and exactly what it means). I ran with -Xdebug.loadService.timing=true and I start getting output in one or two seconds, so the JVM and the JRuby runtime has started executing in that time, that part is not slow at least.
I can see that it takes 15s between JRuby starts running Ruby code until the first test has run. First it’s core (jruby.rb, ~300ms), then Ruby core (jruby/kernel.rb, ~100ms), RubyGems (~500ms). Then it starts loading the libraries my app depends on, and there are a lot of things in the standard library that take on the order of 500ms to load.
time reports 40s of real time, which sounds about right: 15s for loading Ruby, 25s to run the tests.
Running just ruby -e 'puts 1' takes less than two seconds, and could take a lot shorter if RubyGems wasn’t always loaded (try it yourself: time ruby -Xdebug.loadService.timing=true -e 'puts 1').
ruby -e 'puts 1'
time ruby -Xdebug.loadService.timing=true -e 'puts 1'
Having a runtime without a GIL, being able to load any Java library as if it were a Ruby library, and the performance makes it a very appealing platform for me, but YMMV.
I’ve always been curious about the level of adoption of JRuby among Ruby developers, and those administrating Ruby apps. Charles Nutter did(does) remarkable work on that project. Does anyone have information on this?