Jacob Swanner Development Blog

Ruby executable invocation

Since the proliferation of Bundler, we’ve had multiple options for how to invoke Ruby executables; each option has its own set of advantages & disadvantages. The easiest form of invocation is to use the executable that is installed when the gem is installed; things like: rails, rake, or rspec. But, this form of invocation suffers from the problem of potentially loading a version of a gem that differs from the version your project bundle requires; you know you’ve run into this problem when you see a message like the following:

You have already activated <gem-name> <version-x> but your Gemfile requires <gem-name> <version-y>. Consider using bundle exec.

Binstubs

To get around the above problem, we often prefix our executables with bundle exec; and, while this works, I’ve often felt that the execution time was noticeably slower. But, Bundler provides another solution to this problem: binstubs. I don’t think this option is as well known as bundle exec, but this is how you create them:

$ bundle install --binstubs

Or:

$ bundle config bin bin
$ bundle install

Both of the above options will install all the executables that are provided by your bundle in the bin directory, you can then invoke one of the executables like this: ./bin/rspec.

RSpec executable benchmarks

I was interested in benchmarking the various options, to see how they actually stack up to each other; I also wanted to see how funny-falcon’s performance patches affected the execution time – which you’ll see in the 1.9.3-p194-perf column. I have a separate post with instructions on how to install these patches. So, first off, I wanted to benchmark executing rspec1 – all the times are listed in seconds 2:

Command 1.9.3-p194 1.9.3-p194-perf
rspec 0.27 0.22
./bin/rspec 0.49 0.40
bundle exec rspec 0.98 0.75

So, my plan going forward for executables like rspec: use the regular gem executable. If I run into a version conflict, hopefully I can fix the issue by upgrading the gem in the appropriate projects; if that is not an option, then at that point I’ll switch to binstubs for the effected projects.

Rails executable benchmarks

Just running rspec does not necessarily load your whole Rails application. So, the following table shows invoking rails runner '' 3, to see what impact that has on run times.

Command 1.9.3-p194 1.9.3-p194-perf
./script/rails 1.10 0.83
rails 1.27 0.95
./bin/rails 1.53 1.11
bundle exec rails 2.01 1.47

I showed all the options for comparison’s sake, but I actually don’t think there’s any reason not to use ./script/rails; and, luckily my Rails command shortcuts take care of that for me.

  1. No specs were actually run, the benchmarked command was rspec -h, just enough to load Ruby and RSpec. Version 2.11.1 of RSpec was used.

  2. Times were measured with time, only displaying the “real” value, and are the average of 10 executions.

  3. Version 3.2.6 of Rails was used.