Why is rails bootstrap so slow and what can I do about it?

Solution 1:

Check out spork. It essentially runs a small server which runs the bootstrapping and then waits for test runs, allowing you to bootstrap once and then test many times from that state. You will occasionally have to restart it if you do certain kinds of changes to the configuration, but for the most part it lets you have really fast red-green-refactor iterations.

Solution 2:

To quote Yehuda Katz:

There are things that the C require code does in 1.9 that slow things down. One such example is re-checking $LOAD_PATH to make sure it is all expanded on every require. This is something that should be addressed by ruby-core. I’ll open a ticket on redmine if there isn’t one already.

I am also experiencing this problem and a $LOAD_PATH issue seems like a potential cause. Lets hope it gets fixed soon.

So it sounds to me like you'll just need to suffer through this and hopefully it will be fixed in Ruby 1.9.3.

Solution 3:

the problem seem to be the slowness of require, if you do some minimal profiling like

CPUPROFILE=/tmp/my_app_profile RUBYOPT="-r`gem which perftools | tail -1`" ruby -I lib:test test/unit/user_test.rb
pprof.rb --text /tmp/my_app_profile

you should probably see a lot of time being spent in require (another option is seeing a lot of it in loading fixture but I guess you already know that is not the issue).

In my box (osx on a macbook pro 2011 13", with core i5 and a spinning hard drive), the time is more in the order of 5 seconds, which is still a lot but way more tolerable, so maybe it's worth investigating differences.

How many gems do you have installed in your system? Have you tried running the tests/booting without bundler/rubygems?

Solution 4:

It is a tradeoff to pay for not having to write 'require' statements. Rails is trying to do the right thing, and therefore preloads everything. Basically you have two solutions:

  1. Use preloading library that spawns Rails process (spork for example)
  2. Don't use Rails in your tests, extract domain that you can test outside of Rails (Destroy All Software has one screencast about this). It boils down to skipping loading Rails, when possible.

With all that said I am, using solution 1). and having my suite run under half a second (only 70 tests, but waitng for Rails to load is minimal)