You may have noticed that PHP scripts that echo a lot of content appear to be running with poor performance...

Well, the operative word here is "appear". It is a common misconception that "echo is the slowest PHP command"! :p

The problem is actually just a bandwidth issue! When you try to pump a lot of content though the Internet, at some point you experience "load time"... and at some point PHP actually experiences "send time"!

You may measure the execution time between the begining and the end of your script, and, on a slow connection, it may show you that it took 500 ms to execute. You may even narrow it down to a single echo statement that takes 480 ms to execute. But that time actually includes wait time where PHP cannot send any more data back to apache!

There is a common trick that consists of starting output befering before echoing, like this:

ob_start(); 
echo $a_lot_of_content;

This will allow PHP to move on and appear to terminate fast. But the truth is, all the content is now in PHP's output buffer, and although your script is done, PHP is still working in the background to send all that data to your web server (apache for instance).

To verify that the processing time doesn't vary by employing this trick, you can log actual request processing times in apache.

Now, if you want PHP to really terminate, you need to give Apache a larger buffer in order to absorb the content from PHP. I believe the default Apache buffer is 4096 or 8192 bytes (anyone know how to verify this?).

If your PHP script tries to output 24 KB of data but apache can only buffer 8 KB, then yes PHP will be waiting. However, if you make the Apache cahce, say 32 KB, then PHP will send all its data to Apache and exit in a breeze!

Here is how you can change Apache's buffer size in apache2.conf :


<IfModule mpm_prefork_module>
   StartServers          5
   MinSpareServers       5
   MaxSpareServers      15
   MaxClients           40
   MaxRequestsPerChild  20
   SendBufferSize    32768
</IfModule>

The only important line in the SendBufferSize line. The other lines are provided for context so you can find the right place in apache2.conf to add the SendBufferSize line (in case it doesn't exist already). I don't have particular recommendations on the other lines at this point.

After restarting apache, look at your logs and execution times again. You will see them drop from 500 ms to 30 ms in the example above. That is, of course, as long as you don't send more data in PHP than the Apache buffer can absorb.

Now, of course, this will *not* increase the end-to-end transfer time of the page from PHP to browser. However, it will allow PHP to exit faster, which may or may not free up resources on the server... probably depending on the configuration.

I am pretty sure it does free up resources if you use CGI. But if you use mod_php, I don't know... Anyone?

Then, I guess, the next step would be to push the data out of Apache faster... but I'm not sure there is another buffer that could be augmented in between Apache and the actual Nagle Algorithm that manages the transfer speed.


Comments from long ago:

Comment from: ThimbleOpenSource

Just wanted to say thanks. I was struggling with this for quite some time.

2009-12-23 17-37

Comment from: Zeecontainer

Thanks for this usefull information, saved me a lot of time with coding my new php website.
Keep up the good work !

Best regards,
Zeecontainer

2010-10-25 19-28

Comment from: web hosting reviews

I experienced poor performance on my website. I followed the steps in your tutorial and my website is much faster. Thank you for tutorial, it helped me a lot

2011-03-05 21-36

Comment from: Andy

So what size should the SendBufferSize be?

2011-03-06 12-42

Comment from: Ilya Cheburaev

Strange, but with mpm_prefork_module it does not helps.. may be something else?

2012-07-13 08-31

Comment from: Tim Wassman

I actually could not find the parameter SendBufferSize in the apache2.conf file. Also i could not find the other lines you provided.

2015-06-25 15-47