简体   繁体   中英

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

Rails 3.0 is a serious dog. I've been developing on Rails for 5 years, and it's never been slower to startup. In particular, tests take forever to bootstrap on a top notch MacBook with SSD, so iteration cycles suffer severely. I need to read an article every time I start a test. It's insane and not "agile". I might as well be compiling.

This is the major motivation for me to finally move on from Rails - when I have the chance.

If anyone has a solution, please offer it. I know many people suffer from this problem.

I don't use rspec - I know there is a solution to help with tests for rspec.

I'm using faster_require and rails-dev-boost, but there is no significant impact.

I'm on ruby 1.9.2 and need to be. A single pretty simple controller test takes 26 seconds on a dual core 2.13 Ghz MacBook Air with 4Gb RAM and SSD! Why!?

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.

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.

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?

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)

Yes, it's rediculously slow. Oh wait, mvn install in my java days never took less than a minute. With mvn clean install it was crazy slow. Happy days, remembering always gets my spirit up.

+1 spork , as @hammar suggests

combine with guard https://github.com/guard/guard-test for auto-starting the tests and you have a killer combo. Have it running in it's own window and/or screen and see your productivity go up :)

Update/addition to answer:

Optimization tip: put a to_s on paths added to autoload_paths, in application.rb, avoiding it to manually do this over and over again runtime. Might shave off a few seconds...

As @user185374 says, you're paying the tradeoff of the require .

I stumbled upon an interesting resource to speed up Rails tests without using Rails ... The example is given with Rspec but you'll have the logic.

Here is how the writer sums up:

I can't tell you what it means to run all of my 150+ specs within 2 seconds. I think it's a little bit of an extra work, but it's well worth the effort!

Another solution I just found: Hydra parallel testing:

http://logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/

This is a known problem, especially on Ruby 1.9.2.

The good news is that there's a patch to speed up Ruby start-up ( require ) immensely.

Good news. Rails starts within a tolerable amount of time after upgrading to Ruby 1.9.3.

Check out the zeus gem .

This should speed things up quite significantly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM