28

From my previous question I understood that Rails creates a controller instance for every request.

My question is, because this subject is related to the design of the project I'm working on:

Why does Rails creates a new instance of

class SomeController < ApplicationController; end

to process every incoming request? Why not just create singleton object and forward requests to this one? This seems more efficient as we won't waste resources on allocating and cleaning objects for request?

Community
  • 1
  • 1
megas
  • 21,401
  • 12
  • 79
  • 130
  • 1
    Good question, you should ask DHH about that :) But i think the main point is to isolate absolutely one environment to another. Because otherwise system has to spend more processing power for distribution logic. imho – Valery Kvon Jan 05 '13 at 15:12
  • 3
    Because it's easier to reason about code when there's no risk of stomping on another request's data. – Dave Newton Jan 05 '13 at 15:40
  • No surprises, but it appears that Grails does the same thing. –  Jan 11 '13 at 19:56

1 Answers1

42

The overhead of instantiating a new controller instance is insignificant, and it means there is no accidentally shared state between two completely unrelated requests. Any "savings" in processor time would be more than offset by the potential to produce devastating bugs.

Remember that controllers are for storing request-specific state. Reusing controllers would require you to reset every @variable you'd ever set, at the start of every action. Otherwise, something like @is_admin = true could wind-up being set and never cleared. The less contrived bugs you'd actually be introducing would be much more subtle and draining on developer time.

You're seeing optimizations where there are none. Something must maintain state and reset it between requests, or you have this nightmare of accidentally shared state. If you persist controller instances between requests, you're simply pushing the job of maintaining/resetting state down to some lower level, where the answer will likely still be to instantiate a fresh instance of some state-managing class for each request. Computers are very good at allocating and freeing resources, so never worry about that until you actually know it's a bottleneck. In this case, instantiating a new controller for each request is easily the correct choice.

In the case of Rails, being able to use @variable = value is a major win from a code-clarity and usability stand-point, and this more or less necessitates discarding each instance of a controller when the request completes.

user229044
  • 232,980
  • 40
  • 330
  • 338
  • 4
    Well... it's not so much that `@foo` would always need to be cleared, rather that controllers would need to be written to not have shared state, like Java servlets. You'd pass values to the view layer using a different mechanism (locals, the request, etc.) as in Java. Controllers are only for storing request-specific state *because* they're instantiated per-request--it's not intrinsic to the concept of a controller, though; other frameworks do it differently. I know you know that, just clarifying. – Dave Newton Jan 05 '13 at 15:49
  • 2
    @DaveNewton Yes, I considered getting into this, but the question is about performance so I considered it covered by the "someting must reset the state between requests". The jist is that, there is no gain *performance* wise by keeping controller instances around. You're just moving the allocation/deallocation around. – user229044 Jan 05 '13 at 15:52
  • 1
    Agreed, and I much prefer instance-per-request: less thinking. – Dave Newton Jan 05 '13 at 15:54