Hi there,
After having major problems in production where we weren't able to
respond to more than a few requests a second; I did some profiling.
Nothing in our code seemed to be the cause. After putting my own code
into the Rails Dispatcher, wrapping the call to the controller in
ruby_prof, I discovered something weird -- all the view templates in
all the plugins were being recompiled -- EVERY REQUEST.
This was adding a whole second onto the amount of time required to
process a request (obviously, if you don't have view templates in your
plugins you won't have a problem here -- we have 247). So 100
requests takes at least 100 seconds to process, doing 24700 template
compiles. This is basically completely CPU-bound, which explains why
our servers were exploding under reasonably small loads.
It seems that the way the view paths from the plugins were being added
was wrong; basically they're just added temporarily to the view paths,
so every request re-adds them. The problem with this is that when the
eager_loading of templates is turned on (i.e. cache_classes = true),
this recompiles all the templates in the path. So that happens every
request.
In our desert_extras plugin we use to add a couple of features that
are missing (that we used from Engines), I've put a monkeypatch to
undo the change to ActionView::Base, and to load the view paths at the
correct time (in the Rails Initializer).
Code here:
http://code.moneyspyder.net/desert_extras/trunk/lib/desert_extras/fix_view_loading_bug.rb
We've gone from our staging slice being able to handle 66 requests/
minute to around 1100. So this is a patch worth applying.
Simon Russell
Moneyspyder