6

When Rails starts it preloads all of its dependencies (gems), which results in very slow startup time. In a medium sized project I'm working on, the start time of Rails is 10-15 seconds depends on the machine.

While this is not an issue in production, it is a huge pain in development. Specially when working TDD/BDD. There are solutions to speed up the tests (like spork), but they introduce issues of their own.

My question is: why not require the needed dependencies in each of the code files, instead of preloading everything during startup time?

What are the downsides of manual requires? The extra lines of code?

arikfr
  • 3,311
  • 1
  • 25
  • 28

1 Answers1

3

Rails is not PHP. Some resources are autoloaded, but all of the ones that you're likely to need are loaded on boot/initialization because it is better to do so before requests are being made so the application is ready than to lazily load them on request, slowing down the first request. A lot of this last-minute on-the-fly definition of methods and loading of classes still happens, cutting down load time to a mere 10-15 seconds, but if you cut 5-10 seconds off of that load time, it'd just be tacked onto the first request. No good, right?

A lot of the load time you experience is in the gems/plugins/libraries that you add to your project. Many of significant size offer ways to load only the portions that you need, and plenty more could use this optimization. For example, if you have a Rails project that doesn't need Active Record, you can replace:

require 'rails/all'

…with:

require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"

…in your application.rb to cut back on loading (and avoid errors about the database not existing).

coreyward
  • 77,547
  • 20
  • 137
  • 166
  • This makes sense, but if the problem is only in production/first request, there are other ways to solve it. Why impose penalty on development? – arikfr Oct 03 '11 at 16:41
  • To keep development and production closer together, I would assume. Rails helps alleviate the problem in development by not caching many classes, reloading them on each request for you so you don't need to stop and start the server so often. If you have other recommendations on how to accomplish this, I would love to hear them, and I'm sure the Rails team would love to see a patch with improvements. – coreyward Oct 03 '11 at 16:43
  • It's not a penalty. It's the cost of doing business -- you'd still get the delay on the first page load for your development server, too. It's just a matter of whether there's a delay on your command line or a delay in your browser. – Kelly Oct 03 '11 at 16:45
  • @coreyward development isn't the same as production even today, because there is no class caching in development. As for possible alternative solution: how about making explicit requires in each file, and in production preloading everything using bundler (just liek today)? It will solve the first request penalty, while removing the penalty on development, no? – arikfr Oct 03 '11 at 16:49
  • @Kelly, it is the cost of doing business today, but it doesn't mean it have to be like this. – arikfr Oct 03 '11 at 16:49
  • @coreyward re. the option to load certain parts of Rails: it's a nice improvement, but it seems most delay comes from preloading all the gems. – arikfr Oct 03 '11 at 16:50
  • @arikfr: Requiring with `require` in each of your files won't help you any. It'll just waterfall down and load everything anyways. And it'll be a lot more verbose and make adding a Gem a f**king nightmare project involving adding `require 'acts_as_something'` to *every single model that uses it*. No thanks. – coreyward Oct 03 '11 at 18:02
  • By the way, caching classes doesn't tend to cause any problems because the difference in behavior isn't very significant. You can turn it off in development if you need to, of course. It's quite easy to do in `development.rb`. – coreyward Oct 03 '11 at 18:04
  • @coreyward it will load only what you need. If you happen to use every piece of code in your project, then yes, it will require everything. But if you happen to run specs for a single class, it will load only its dependencies -- shortening the startup time in order of magnitude. Globally used objects (like `acts_as_something`) can be required in application.rb or similar location. – arikfr Oct 04 '11 at 05:40
  • And I know about how caching classes in Rails works and that it usually doesn't cause issues. I just gave it as an example for another difference between production and development. – arikfr Oct 04 '11 at 05:41