NOTICE: Don't even try this on 2.0... It's tested against 2.1.2 only but I plan to have it working on 2.2 soon.
Once upon a time there was dev_mode_performance_fixes. I was on a Powerbook at the time and almost crying from how slow Rails 1.2 was in development mode for any non-trivial app.
Then things changed...
Rails went 2.0, I got a Macbook Pro, and the plugin was all but forgotten. I think there was some minor interest in making it work with 2.1 but I didn't pay much attention because it really wasn't an issue for me anymore.
...and many moons came and went.
Today I'm proud to announce rails_dev_mode_performance. It's the original plugin reborn. I'm seeing an order of magnitude (12x) improvement in performance.
It's mostly a port of the old code to Rails 2.0 with all new hacks to deal with Rail's new TemplateFinder and it's dev mode performance issues. And now it's on GitHub... so if you want to contribute you can e-mail me bug fixes or fork the repository and send me a pull request.
How it Works
How all this works is that we're trying (very carefully) to track every dependency and relationship between objects back to the filesystem. When you edit a file in your application any objects that are somehow affected by that file are flushed and reloaded at the beginning of the next request.
This could mean reloading classes that inherit from a class that was defined in that file... or perhaps you've edited a module that you included in 12 classes... each of those classes have to be flushed before the next request so they can be reloaded to include the new version of your module.
Potential Gotchas
As you can imagine this requires a lot of hooks into dependency loading, modules inclusion, etc... the original plugin was patched numerous time to take this or that edge case into account. I'm sure we'll find more of these edge cases and I think there are probably solutions for most of them.
If you're doing something totally whacked and you know it (loading entire modules and classes from the database would be one thing that comes to mind) then this plugin may never work for you.
I think it can work for most of us though. Please check it out and let me know any bugs or issues you find.
NOTICE: Don't even try this on 2.0... It's tested against 2.1.2 only but I plan to have it working on 2.2 soon.
I assume no go with 2.1/2.2?
I like this patch--my equivalent of it was to run in production mode and kill the server whenever any files changed :)
-=R
http://code.google.com/p/ruby-roger-useful-functions/source/browse/trunk/rails/rails_useful.rb
Posted by: roger | November 10, 2008 at 11:22 AM
Why do you think it wouldn't work with 2.1? I'd imagine it'd work with any of the 2.1.x series, though I've only tested with the later bug fix releases. 2.2 I have no idea but someone is welcome to test it out and file a bug report on Lighthouse if there are any issues - or submit patches. :-)
Posted by: Josh Goebel | November 10, 2008 at 11:24 AM
Hey Josh, nice work - happy to see this on Rails 2! It's a bit spammy though, I see a ton of these on 2.1.2:
DEPRECATION WARNING: Dependencies is deprecated! Use ActiveSupport::Dependencies instead. See http://www.rubyonrails.org/deprecation for details. (called from included at /vendor/plugins/rails_dev_mode_performance/lib/dep_hacks.rb:183)
I skimmed the plugin code, and see that you do use ActiveSupport::Dependencies on some locations, but not all, so I'm wondering if there's a deeper reason for this, or it's just a "todo" thing.
Posted by: Morten | November 14, 2008 at 06:31 AM
No reason. I hadn't noticed the warning when playing around. Simple enough patch though - you can fetch the latest from git.
Posted by: Josh Goebel | November 14, 2008 at 09:34 AM
Great idea...
FYI, tried it with edge (2.2?) and it crashes on start... the template finder seems to rely on some 2.1 file_exists? method, which has been refactored away in 2.2.
Actually, the whole TemplateFinder module is gone in edge. I'm sure someone more familiar with those changes would be more successful than I was in getting it to work :(
[ps, "TemplateFinder and it's dev mode performance issues" -- http://www.37signals.com/svn/posts/1302-its-not-its ]
Posted by: David Reese | November 16, 2008 at 11:59 AM
"its" and "it's" have to be one example of the English language being totally f-ed up and inconsistent. 's is used everywhere else to indicate possession so instead of vilifying this edge case the language should just be changed to allow both uses. In most cases that doesn't lead to ambiguity.
Posted by: Josh Goebel | November 16, 2008 at 01:47 PM
When 2.2 is released I will vet the plugin against it. For now please test with 2.1.2 or try commenting out the hack for TemplateFinder.
Posted by: Josh Goebel | November 16, 2008 at 01:48 PM
Commenting out the template_finder_hacks in init.rb makes it work great with edge. Works great even with the Engines plugin -- not sure why but I was surprised to see my engine-ized plugin app/ directory reload as needed!
>15x speed improvement!
Posted by: David Reese | November 16, 2008 at 01:57 PM
I just tried it on a rails 2.0.5 project and it crashes on start saying this:
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.5/lib/active_support/dependencies.rb:266:in `load_missing_constant': uninitialized constant ActiveSupport::Dependencies (NameError)
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.5/lib/active_support/dependencies.rb:453:in `const_missing'
from /Users/abuser/Code/unconundrum/intranet/vendor/plugins/rails_dev_mode_performance/lib/dep_hacks.rb:1
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.5/lib/active_support/dependencies.rb:496:in `require'
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.5/lib/active_support/dependencies.rb:342:in `new_constants_in'
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.5/lib/active_support/dependencies.rb:496:in `require'
from /Users/abuser/Code/unconundrum/intranet/vendor/plugins/rails_dev_mode_performance/init.rb:8:in `evaluate_init_rb'
... 38 levels...
from /usr/local/lib/ruby/gems/1.8/gems/rails-2.0.5/lib/commands/server.rb:39
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from script/server:3
Posted by: Tony Buser | November 17, 2008 at 01:50 PM
It's / its is consistent with who's / whose, he's / his, she's / hers, etc. So, yeah, no :)
Posted by: Chris | November 18, 2008 at 01:52 PM
It's not the same at all... they purposely avoid the problem entirely by changing the form of the word.
* hes going -> his moped
* shes running -> her car
* whos there -> whose publication
* its 5-oclick -> its error
In the first 3 cases (apostrophe dropped on purpose) there is a very clear difference and not even the opportunity for this kind of mistake. The last two will always be a toss up in my opinion.
Posted by: Josh Goebel | November 18, 2008 at 03:43 PM
We're still on Rails 2.1.0, and to make it work I had to change
ActiveSupport::Dependencies
to just
Dependencies
in 8 places in dep_hacks.rb. Once I do that it works great. We have 80-something models and it's a huge difference for us.
The following commit to ActiveSupport (4 days after 2.1.0) explains why I had to make the changes:
http://github.com/rails/rails/commit/c08547d2266c75f0a82d06dd91c6d0500740e12e
I notice that there is a rails2_1 tag at github, but perhaps it should be called rails2_1_2 instead.
Posted by: David Vrensk | November 26, 2008 at 08:47 AM
...and I had to make the same change in dispatcher_hacks.rb.
Posted by: David Vrensk | November 26, 2008 at 09:22 AM
Oh wow this is *exactly* what I need for Hobo. Hobo does a TON of extra stuff in dev mode compared to Rails, and performance can be really painful.
Really looking forward to trying this out...
Posted by: Tom | November 28, 2008 at 01:38 PM