– we create awesome web applications

About half a year ago Vitaly posted a post about how simple it is today to use ruby patches bundled with rvm installation to dramatically reduce big rails app loading times and make your dev environment a much happier place.

Since then Ruby advanced with new patchlevels and there are new patches to use, so let’s go over this once again.

First, we start with upgrading the rvm to latest and hopefully greatest

rvm get head

Since Vitaly wrote his post it seems that the railsexpress patch superseded the falcon one. At least that what i got from browsing over the patches repository.

So, next step is to compile our Ruby version with railsexpress patchset applied

rvm install 1.9.3-p392-railsexpress --patch railsexpress

Ok, now for some trivial benchmarking to ensure we made things better and not the other way around. Now, note that the say in the interwebs goes that the bigger your application and amount of gems it has to load the more happy you will be. Also, the usual disclaimer about those performance things, YMMV.

I took a random application from my dev folder. It loads 147 gems. Let’s check out some numbers

✗ rvm use 1.9.3
Using /usr/local/rvm/gems/ruby-1.9.3-p392
✗ time rails runner "puts :OK"
OK
rails runner "puts :OK"  16.28s user 1.70s system 98% cpu 18.185 total

✗ rvm use 1.9.3-p392-railsexpress
Using /usr/local/rvm/gems/ruby-1.9.3-p392-railsexpress
✗ time rails runner "puts :OK"
OK
rails runner "puts :OK"  8.56s user 1.22s system 99% cpu 9.820 total

Just to make a comparison to the previous blog post, here are the numbers for the same application with ruby 1.9.3-p327 with falcon patches set:

✗ rvm use 1.9.3-p327-falcon
Using /usr/local/rvm/gems/ruby-1.9.3-p327-falcon
✗ time rails runner "puts :OK"
rails runner "puts :OK"  9.89s user 1.34s system 98% cpu 11.374 total

So, comparing to falcon patches it’s not that big of an improvement, but still, another 1.5 seconds win.

And yes, i know that both before and after times are slow. But still, i see a nice around 50% time save on any environment loading. And what i really like is that this improvement demanded the whole 7 minutes of my time.

UPDATE [30 Apr 2013]: The new, updated and faster version of this blog post covering Ruby 1.9.3 patchelevel 392 and railsexpress patch set.

I knew that there are various Ruby patches available but I’ve never tried them as I didn’t want to waste time for something that I thought I don’t really need.

Then I found out that rvm comes bundled with patches ready to be applied, so I’m just a simple command line away from having a patched Ruby. Don’t know how I missed that before.

One particular patch that worth trying is falcon. It improves startup time of big Ruby applications. And the bigger your Gemfile is the bigger the improvement.

Try it right now for yourself. It will only take a couple of minutes.

First upgrade rvm to make sure you have the latest

rvm get head

Then the actual Ruby build

rvm install 1.9.3 --patch falcon -n falcon

Note that this command can fail with the following error: Patch 'falcon' not found. The reason is that falcon patch is not yet supported on the latest Ruby patch level, in which case you will need to specify older patch level to make it work.

Find out what patchlevels have falcon support

ls $rvm_path/patches/ruby/1.9.3/*/*falcon* | sort
/usr/local/rvm/patches/ruby/1.9.3/p0/falcon.patch
/usr/local/rvm/patches/ruby/1.9.3/p125/falcon.patch
/usr/local/rvm/patches/ruby/1.9.3/p194/falcon.diff
/usr/local/rvm/patches/ruby/1.9.3/p286/falcon.diff

So latest patch level with falcon support is 286 at the time of this writing.

Install specific patch level with falcon support

rvm install ruby-1.9.3-p286 --patch falcon -n falcon

Congratulations, you now have a patched Ruby installed.

Lets test how much improvement it is. The following is for one of my current projects with about 50 gems:

✗ rvm use default
Using /usr/local/rvm/gems/ruby-1.9.3-p194
✗ time bin/rails runner "puts :OK"
OK
bin/rails runner "puts :OK"  6.47s user 0.60s system 99% cpu 7.106 total
✗ rvm use ruby-1.9.3-p286-falcon
Using /usr/local/rvm/gems/ruby-1.9.3-p286-falcon
✗ time bin/rails runner "puts :OK"
OK
bin/rails runner "puts :OK"  2.79s user 0.52s system 98% cpu 3.354 total

Nice! Startup time decreased from 3.354 to 1.106 seconds. More then twice faster.

I’m going to use this Ruby by default now

rvm use ruby-1.9.3-p286-falcon --default

And while we are on the “lets improve rails startup times” subject, lets do one more change. Add the following to your shell startup file. i.e. ~/.bashrc or ~/.zshrc

export RUBY_HEAP_MIN_SLOTS=1000000
export RUBY_HEAP_FREE_MIN=500000
export RUBY_HEAP_SLOTS_INCREMENT=1000000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
export RUBY_GC_MALLOC_LIMIT=100000000

This will tune Ruby GC settings to be better suited for running big apps (as it seems to be tuned for small Ruby scripts by default).

Lets see how much improvement that is

time bin/rails runner "puts :OK"
OK
bin/rails runner "puts :OK"  2.27s user 0.58s system 98% cpu 2.890 total

Total improvement from 7.106 to 2.890 is almost 60%.

Now, stop fiddling with the environment and go back to creating something great! :)