By Craig Buckler

Speed Up Your Website With PHP Buffer Flushing

By Craig Buckler

PHP output buffering is normally enabled by default. In older versions of PHP, a string would be sent to your browser every time the interpreter encountered an echo statement or text outside the PHP delimiters.

Output buffering makes this process quicker and more efficient. The buffer is essentially a big memory-resident string. When text is output, it’s appended to the buffer rather than returned to the browser immediately. The buffer is then “flushed”, i.e. its contents are transmitted and the string is reset pending further output. Flushing occurs when:

  1. the PHP interpreter reaches the end of the page
  2. the buffer exceeds the number of bytes specified within PHP’s output_buffering configuration setting, or
  3. the flush() or ob_flush() functions are called.

There are a few caveats but, assuming it works within your environment, you should consider flushing the buffer immediately after the page’s </head> tag, e.g.

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8" />
<title>Buffer flushing in action</title>
<link rel="stylesheet" type="text/css" href="styles.css" />
<link rel="shortcut icon" href="favicon.ico" />
// flush the buffer

(If you’re using WordPress, you could use similar code in your theme’s header.php file.)

Once the browser has received the HTML head, it can begin to download all linked CSS files, favicons and other resources. These downloads can occur while the browser is idle and waiting for the main body content.

The speed increase will depend on the server-side processing required, the weight of your page, the quantity and size of your CSS files, and whether the browser has cached any resources. However, it’s such a simple optimization, there’s little reason not to do it.

I’d be interested to know whether this technique results in a perceivable speed difference on your website or application.

  • You might be interested in some benchmarks I did using this technique a while back:

    The sum: flushing the head under certain scenarios does increase overall page load time.

  • wesley

    That’s interesting (though nothing new, yahoo has been advocating this for years). However, there’s a few things worth mentioning:

    To get maximum benefit, the (head) section should be flushed before you do your database queries (because most time is spent there server side).
    However, we usually only output the actual template until after all db fetches have been done (as is the case in most MVC approaches and most likely wordpress as well). So the benefit is small if you don’t change the processing of your server side infrastructure.

    Add to that the fact that you can no longer send additional headers after you’ve flushed, this means you can no longer redirect. If you have delayed your db queries until after this flush, you could for example no longer send a page not found error header if the input does not match a row in the database. If you have any solution to this problem I’d love to hear it.

    • That’s a good point and I doubt many existing MVC approaches solve it. Off the top of my head, you’d need some sort of 2-pass controller which works out the basics of what the page needs to do (redirect, standard header, etc.) then does the body database queries and view output.

      However, a flushed header could still have benefits with existing MVC apps. The browser can start parsing sooner, especially if the page content is huge and take several seconds to arrive.

      • You don’t need 2-pass controller, you just need a templating system that allows you to call methods (directly or indirectly through __get). Then you can fetch only the critical data (for example the article row) before passing the control to template (to find out if you don’t need to output 404). All other data (like discussions) can be read from the template. The procedure is this:

        1. Check if the item exists (or output 404).
        2. Print the first part of template and flush the output.
        3. Read all other data by calling methods from template.

  • I went ahead and gave this a try. I figured that with three stylesheets and a js stylesheet switcher, my site’s a perfect candidate. Not sure if I’ll notice a difference, but it can’t hurt.

  • There is one buffering done by PHP (started by ob_start() or its equivalent) which can be flushed by ob_flush(). But there is also usually a second buffering done by a web server which can be flushed by flush(). For example Apache buffers the data up to the SendBufferSize setting.

    Thus the article is not precise, mainly the point 3. You usually need to call ob_flush() and then flush().

  • Sorry Craig, but this isn’t especially useful at all.

    1) If you flush, you can’t gzip. And you can’t zip the outgoing string until you’re done. With large pages gzipping the page will make the process faster than flushing the output in pieces.

    2) Any site that makes use of the X-JSON header approach to get data from PHP to javascript without cluttering the page with inline script can’t do this since the contents of that json object will usually not be able to be determined until after the page is nearly complete. I suppose an inline script block could be tossed in before the closing tag, but it feels messy to do that.

    3) Most if not all MVC frameworks end up building the page out of order, sometimes very out of order depending on their architecture. This is due in large part due to their class based nature. To make use of this would almost require a return to procedural page building.

    • Schepp

      Argument 1) is not true, as you can do flushing together with ob_gzhandler.

  • It’s also worth pointing out, along with interfering with gzipping, that using flush() can interfere with caching plugins for WordPress (WP-Super-Cache and W3-Total-Cache) etc.

    However, implemented correctly – and under the right circumstances and environment – then flush’ing can be beneficial.

  • neil_metaflow

    Interesting idea…

    I only ever call ob_start() when I’m using sessions. I do that to reduce the chance of getting annoying “header already sent”. errors. Even then, I only delete the buffer when someone logs out of.

    For what it’s worth, these are the “low hanging fruits” I go after:

    Run as few queries as possible, using joins and grouping in a single query instead of doing three separate queries to gather the same data. Sometimes It takes longer to figure out how to do it in fewer queries, but it’s totally worth the headache!

    Another, perhaps simpler thing is to use built-in PHP functions wherever possible. If I can’t think of simple way to do something I always check the list of functions on the PHP site before I think about writing a custom function. A built-in function will always run faster because it’s written in C!

    Just thought that might be of interest to some

  • David

    How would this compare with using far-future expires? That way external resources are only downloaded once. I can’t see how flushing would be much benefit in this case except for maybe the initial download. Even then, you could prefetch larger downloads after the current page is loaded, and before you actually need them.

    eg. if you need jQueryUI, for the rest of your site, but the login page doesn’t need it, include library after the login page has loaded. That way the user can log in without having to wait for the whole thing to download, but it will be ready for use once logged in.

  • I have a question related to this line: “(If you’re using WordPress, you could use similar code in your theme’s header.php file.)” in article.
    I thought that it can help any average WordPress user. Any good or avg user will use caching then how can this help?
    Can the above addition of ob_flush(); work in cached version of page?

  • While the theory is sound it creates some significant issues. If you’re generating the page from a database record (e.g. a shopping cart product page) this makes it impossible to set the page title/meta description from the result (or include arbitrary js/css based on the state of the final output).

  • jestempies

    This has very limited use at best. If we’re talking about the homepage of Yahoo, sure, go nuts. But this limits what you can do (i.e. you can’t set the page title from DB data) and on second pageview page resources are usually loaded and cached, so this wouldn’t gain much of anything.

  • Hi,
    Thank you for this article.
    I have a question.
    For example, if in the HEAD section i have a javascript with an window.onload instruction that selects some html elements from body, then i call flush() before the BODY.
    This will send the HEAD code to browser, but if the BODY isn’t added in that moment, doesn’t it affect the JavaScropt code.
    Or, the window.onload will know and wait till the whole html page is loaded?

Get the latest in Front-end, once a week, for free.