Yahoo has been researching various different techniques for improving website performance. There are a lot of obvious ones, such as making sure images are optimized, JavaScript/CSS is minified and so on.
There are also a couple of less known tricks, such as putting JavaScript as the last in the document, and “flushing early”.
Flushing early basically means that when you are generating your page, you should send data to the browser as soon as possible. A lot of frameworks (including Zend) buffer the whole reply before sending it, and it started bothering me…
The theory
So what’s the idea behind this?
Imagine the typical setup: You have a page, with CSS and all the usual stuff. Usually the “header” of the page is relatively static: There is just the title, meta tags, stylesheets and such.
Then, after the header, you usually have the contents and such. They are fetched from the database or such, and usually it may take a bit to query the DB, process the results and so on.
Then you have the footer.
Now, as we can see, the header could be sent to the browser even before the database is being queried for content. This could improve the speed the page is loaded and the perceived performance. The user’s browser could already start loading things like CSS, and your site would be querying and processing data the same time, and it could then send more data when it’s done doing its thing.
This is what frameworks usually aren’t doing. They do all the heavy processing before sending out a single byte.
In practice
In the case of Zend Framework, this means we will have to hook in the whole process of what’s going on behind the scenes. ZF is sticking all the HTML and such in the response object. The last thing which happens in the process is the response being sent to the browser.
Now, we could just take the response object and extend it so, that it immediately sends out any data put in the response’s body. In theory this could work, but there are some problems caused by the way ZF works.
The problems
- The response is only getting any data in the body after the heavy processing is done. You would have to manually put something in there, even before any action controllers are called.
- Zend_Layout uses the response’s body to insert data in the layout
- View helpers like HeadTitle and HeadMeta would lose their purprose, as when you send the header part of your page, you no longer would have any control over what’s in there.
Implementation ideas
To make something like this feasible, the framework would need some kind of a method to tell when the content is ready to be delivered.
– I’m done modifying the header. Please send it to the client.
Doing this would be possible by perhaps modifying Zend_Layout and the response class so, that they could support flushing the output buffer. You could modify the page’s title and such in your action, before actually performing any possibly slow operations, like DB queries.
The response class would need to be extended or modified to support something like response segments, which would allow you to send the response in segments: First maybe just the HTTP headers, then perhaps the initial html, head, title and link elements, then the actual content fetched from the DB and the footer.
To support this, you would need to be able to define segments in the layouts. I’m not sure how this would be best implemented, but you would need to be able to tell which parts of the layout can be sent beforehand. For example, you could just do your HeadTitle modifications in your action, then call something like $this->_response->sendSegment(‘header’);, which would send all the unsent segments before header and then the header segment.
However, implementing something like that in an efficient and easy to use manner would not be very simple. If it was, I’d be providing you some code right here to do it, and not just talking about it. The first thing to spring to mind is that if it worked like I outlined above, you would need to put sendSegment(‘header’) in all of your actions so that it would get sent before any heavy processing…
Conclusion, for now
Seeing that Yahoo does not provide any actual data on how much the performance is improved by sending data early, the problems caused by that and the difficulty of implementing things like layouts and the head-helpers, greatly seem to outweight the benefits of such optimization methods.