Speeding up jRuby initialization for TDD

JRuby has always been my favorite Ruby-Interpreter. You can write Ruby and have access to the whole Java/JVM ecosystem. Great!

Unfortunately jRuby's start up time has always been a huge annoyance but seems to have gotten worse with the introduction of JAVA 8.

When developing Ruby in a TDD fashion (which is the way you should be working IMHO) jRuby's start up time gets really in the way of your developer happiness. Fortunately there exist several projects that try to improve the start up time of jRuby by preloading a JVM-Environment.

You can use

  • Spork (kind of works with JRuby but I had some issues when running specs)
  • Drip (works, but not with Rails commands like rails console) [1],[2]
  • Theine

The only thing that really worked for me was Theine.

The embedded video shows how a TDD-workflow with Theine looks like.

theine-tdd

In the video you can see me:

  • start up the Theine server with `theine_server``
  • attach to an existing tmux session with tmux attach -t which I aliased to ta
  • create a mapping to run the current file through rspec with Theine via <leader>r inside vim.
  • execute the spec file
  • detatch from the tmux session
  • close the Theine server

This makes for a nice TDD-workflow in my opinion. In real life you would likely use a vim-plugin like vim-rspec to fire of the spec file in focus but the video is just meant for illustration purposes and tries to make the workflow transparent.

Also interesting and which I did not know about before having a look at this recently. When using rvm you can create custom after_use_<ruby-version> in your rvm directory.

This can be used to additionally speed up Theine's start up time considerably. For example I created a hook after_use_jruby_theine in my ~/.rvm/hooks/-directory:

#!/usr/bin/env bash

\. "${rvm_path}/scripts/functions/hooks/jruby"

if [[ "${rvm_ruby_string}" =~ "jruby" ]]  
then  
  jruby_options_append "-Xcompile.invokedynamic=false -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-noverify -Xcompile.mode=OFF"
fi  

After creating a hook like this you have to make the hook file executable and rvm will run it when switching to a jruby-version.

chmod +x $rvm_path/hooks/after_use_jruby_theine  

You can have a look at https://github.com/mrbrdo/theine#jruby-settings for more details about this.

jRuby + Theine + rspec + tmux + zsh

I do all my development in the terminal and use Tmux as my terminal multiplexer. This is pretty useful when developing Rails or Ember applications because you do a lot of stuff in your editor of choice and a lot of maintenance work in the terminal (e.g. starting and stopping development servers etc.). But...

When running inside tmux starting Theine did not work for me. This was not a huge surprise because all MacOS-LaunchAgent stuff also does not work when run from inside Tmux so the easiest solution for this is to just start Theine outside of Tmux. ;)

When using an rspec-plugin for your editor like vim-rspec you should also make sure that Tmux is using the same shell as you started it with otherwise rvm initialization will run twice and will screw up your $PATH.

You can add the following code to your ~/.tmux.conf to make sure everything is set up properly:

# start tmux with a login shell otherwise rvm will complain
set -g default-command "$SHELL --login"  
# use your normal shell with tmux
set -g default-shell $SHELL  

You should also make sure you have moved /etc/zshenv to /etc/zshrc when using zsh so dispatching an rspec run from your editor works as expected. [3]

Hope this was useful to someone and happy TDDing with jRuby!

[1] Using Drip with jRuby

[2] Github Issue - Limits of Drip

[3] Installation Guide vim-rspec

comments powered by Disqus