

Ruby 2.0 patch that could make Rails startup 2.2x faster - lest
http://bugs.ruby-lang.org/issues/7158

======
petercooper
Some extensive background to the speedups that occurred in 1.9.3 with regards
to loading so far along with the Xavier Shay work that didn't get included:
[http://www.rubyinside.com/ruby-1-9-3-faster-loading-times-
re...](http://www.rubyinside.com/ruby-1-9-3-faster-loading-times-
require-4927.html)

~~~
kiba
Why didn't it get included?

~~~
petercooper
I don't recall seeing a definitive reason given but I'd always assumed it was
because Xavier's patch was _very_ large and the Ruby core team are usually
conservative with these things. The solution _they_ came up with was merely a
few lines of C. It was a bit of a cheap hack but provided much (but not all)
of the real world benefit, so they went with it as it was easier to audit.

------
jordanthoms
This is exciting, the load time is one of the things that is most painful for
me when working with Rails. It's really great when you can just add gems and
get things working quickly but the load time tends to shoot through the
roof...

Spork etc help but you still end up spending a lot of time waiting.

~~~
kiba
Rails tests that takes too long are also painful too. If you try to speed them
up, you might run into the problem of having to restart from scratch when you
write stuff that need restarting to take effects.

~~~
agotterer
Check out spork - <https://github.com/sporkrb/spork>. It keeps your rails code
running so that you can run tests fast. Great for development, saved me 11
seconds every time I ran rspec.

------
gingerlime
The falcon patches for 1.9.3 together with GC tuning boosted our rails loading
time by over 400% (Thanks to the answer on
[http://stackoverflow.com/questions/12892937/improve-rails-
lo...](http://stackoverflow.com/questions/12892937/improve-rails-loading-
time)). It's easy to see how required gems add up to the loading time, so I
hope to see some more improvements.

This affects a lot of things: going into the console, running the server,
running tests, running migrations, rake tasks etc...

Not trying to start a flame war, but I recently compared a live rails project
with another live django project I was working on. Django was loading in under
1 second. Rails took almost 50 on a similar-spec host. Apples and Oranges. I
know. After applying the falcon patches it dropped down to around 11 seconds.
There's still an order-of-magnitude difference, but it's nice to see things
going in the right direction.

~~~
mcmire
Yeah, I immediately thought of the falcon patches too when I saw this. Does
anyone know how they compare to these patches?

~~~
price
Hi, patch author here. Two of the falcon patches address the same two issues
as my patch series. One caches the expanded $LOAD_PATH (which is expensive to
compute mainly because it involves allocating a lot, typically hundreds of KB,
and the Ruby GC isn't very efficient), which my patch #4 does. Another speeds
up searching the $LOADED_FEATURES array -- his patch keeps it sorted, while my
#3 leaves the array unchanged but maintains a hash table pointing into it.

The main difference between the patches is how we maintain the needed
invariants, as both $LOAD_PATH and $LOADED_FEATURES are visible to Ruby code
and actually mutable from Ruby code. The falcon patches put singleton methods
on each of those arrays, wrapping the methods that mutate arrays in order to
make them maintain the invariant. This is a very general approach that could
implement any desired behavior, but it is relatively complex in the number of
cases it has to explicitly handle.

My patches instead take advantage of a feature of the Array implementation to
keep a snapshot of each of $LOAD_PATH and $LOADED_FEATURES, and on each
'require' call detect whether they've been mutated. If they have, we rebuild
our invariants. This has an advantage in simplicity -- the Array
implementation already must track when an Array is mutated, and we just
piggyback on that. It can cost more time, but never much more than the status
quo (where we must effectively rebuild all the state on every 'require' call),
and in normal usage people rarely mutate $LOADED_FEATURES at all and mutate
$LOAD_PATH in only one or a handful of bursts, rather than alternating
mutation, require, mutation, require many times. So in practice it should be
almost as fast as if we never had to rebuild.

NB that funny_falcon himself, aka Yura Sokolov, is participating in the bug
thread, so you can read his thoughts there.

------
ScotterC
For a really fast Rails environment I highly recommend Zeus
<https://github.com/burke/zeus> which is built in Go. It does a great job of
reloading only the dependencies that have changed.

~~~
mcmire
Agreed, although improving load times all across the board is surprisingly
helpful. It can make restarting your app in production after a deploy faster,
for instance. If anything it just makes you happier in dev if you're running
some Ruby command outside of Spork or Zeus.

~~~
ScotterC
I'm not sure if I fully understood your comment - You've used Zeus in
production?

If in reference to just improving speeds all across the board - recovery after
deploy is the #1 priority for me. Rolling restarts feel like unnecessary
complexity in deploys.

------
jasiek
Here's a script to install these patches using rvm:
<https://gist.github.com/3993269>

~~~
price
Thanks! For people using rbenv, there's a simple installation recipe in my
first comment on the ticket: <http://bugs.ruby-lang.org/issues/7158#note-1>

------
kiba
For some reason, I thought 2.2x was a version of rails, a really old one at
that. Now I know that it's the speedup. My brain is weird sometime.

~~~
instakill
Thought the same thing at first.

