The HTTP protocol is defined to be stateless. For a protocol that allows an essentially non-linear look into a linear, static, “book-like”, hierarchical structure called web page, that makes sense. All the serving application needs to know can be encoded in a single request, which was also done to prevent DoS attacks since the server does not keep any data for any client what-so-ever, thus preventing running out of memory when hit with too many requests.
As soon as web pages started to be non-static and allowed clients to manipulate server-side data, problems abounded. Now there is the need to save state. Think of a typical website that allows you to log in. That login state needs to be saved between requests to be remembered the next time your browser requests a page.
Because of the way the web evolved with its numerous forays into security disasters, browsers employ a rigorous security model. This model exercises severe restrictions on code that is executed client-side as well as disallows any manipulation of permanent storage on the client (too risky – could be used to read files). As a consequence pages cannot save the login state on the client-side. So they had to do that server-side. To ease that cookies got invented. Cookies are essentially a twisted way to remember state server-side but save it on the client. It can only be read and written on the server, but gets transferred and saved on the client, which is not supposed to be able to read or write it (which of course is not true because there are numerous browser plugins and transparent proxies to get around that). And it – of course – gets transferred back to the server with every request. *Shudder*
Scripting languages, like PHP and others, use sessions to remember server-side state. Everything that is stored in a special variable – most of the times aptly named _SESSION or similar – gets serialized at the end of every request handling and written to disc (or into the DB) with some special identifier which is subsequently stored in a cookie on the client.
When a new request comes in and has been passed from the web server to the the scripting language for processing, it initializes and bootstraps its VM, picks apart the request, locates, deserializes and loads the session var and then starts loading the code of the framework (Drupal, Joomla … the works). That can easily be a couple k’s of code. Lastly, the FW now examines the session, gets some state from the DB, like logged in user-info etc, and is now ready to look at the request to decide what to do with it – what to render etc.
Again, the framework (lots of code) is initialized on every request – even AJAX.
Of course, there are some shortcuts for this process, most of the VM code is in a cache somewhere and loads very fast, as well as most of the code for the framework should be in the cache also; most page requests don’t need to be re-rendered by the FW because they are cached somewhere as well. One of the reasons why servers benefit from huge (L1 and L2) caches as well as lots of RAM more than desktop machines do. Some VMs even keep a couple idling, fully-FW-bootstrapped (background) worker-threads around, waiting for incoming requests to be passed to them. Ruby on Rails does that, for example – which is very smart in my opinion, because it significantly reduces boostrap time for incoming requests.
Looking at all of that bootstrapping, I wonder if it wouldn’t be more efficient to not the terminate that worker thread at the end of each request but to keep it idling, fully preserving its state for the next request. Before you start crying that that opens a huge DoS risk: I know that, and you could easily only do that for known and logged-in users, thus significantly mitigating the DoS risk.
I do not know, how the Java server-side FWs (Struts etc) do it, maybe somebody can shine a light?
Wouldn’t that make a nice research topic? Measure the performance difference and impact on the server of both approaches.
Anyone (in need of a research topic for their thesis)?