Categories: "Full Stack Dev & Design"
flush() bug in PHP 5.4
For some reason, nobody seems to acknowledge there is a bug with flush()
in PHP 5.4.
In any previous version of PHP, you could just do:
PHP
flush(); |
and the PHP output buffer would be sent to Apache which would in turn send it to your web browser.
We are not talking about any side effects due to compression or charset sniffing here. We are talking about: flush() was working just fine.
And then compes PHP 5.4 and it doesn't work any more. And you revert to PHP 5.3 and it works again. PHP 5.4, broken again. And you can reproduce that to infinity but still, nobody wants to acknowledge it.
So we had to find a workaround. Here it is: just replace your flush() calls with a custom call like flush54() defined like this:
PHP
function flush54() | |
{ | |
@ob_end_flush(); | |
flush(); | |
} |
This will restore the initial behaviour...
Live HTTP Header tracking for Firefox
LiveHTTPHeaders is a FireFox extension that lets you look at all HTTP headers for all requests issued by the browser.
I am updating and resurfacing this post today since -- after a long while of being mildly maintained -- this fine plugin seems to have effective backing again. Version 0.17 works on FireFox 9.x.
Even in the days of FireBug, LiveHTTPHeaders is still an irreplaceable tool in a web developer's toolkit. As a matter of fact, LiveHTTPHeaders is the best way to track chains of redirects, which FireBug doesn't display right, as it will often clear the "Net" tab from one request to the next.
The header tracking window can be opened through Tools > Live HTTP Header. It will then capture all requests and display HTTP headers being sent as well as headers being received. Note that it is possible to stop capture at any time so the display stops scrolling. It is also possible to filter out specific requests (for example images) with a regular expression (regexp).
The extension also extends the Page Info windows with a Headers tab, which is useful if you just want to see the headers for the current page.
Finally, it's also possible to edit requests and replay them again, modified. At this time this is still in beta though, and Tamper Data may be a better extension for that purpose.
Why echo is slow in PHP and how to make it really fast
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:
PHP
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).
How to log request processing times in Apache
If you have an apache (2) web server, you probably have an access.log file showing you all kinds of data using the “combined” log format. Let’s see how to include processing time into that log file.
By default a line in the combined log looks like this:
[codeblock lang="” line="1″]10.0.209.80 - - [03/Dec/2009:03:20:47 +0100] “GET /info-tech/ HTTP/1.1″ 200 46482 “http://fplanque.com/info-tech/” “Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5″[/codeblock]
Notice the 2 dashes - - just after the IP. The first one stands for “I could not identify the user using ident” and the second one for “no user authentication was performed".
Now, let’s face it: you will never identify anyone using ident. Your apache conf probably even doesn’t try. That field is a left over from ancient times. So let’s replace that first dash with something useful, i-e: the processing time of the request! Note that by doing this we keep the global structure of the file identical and any log processing tool you might be using should not be affected.
How to install the APC PHP Cache on Debian (Lenny or Squeeze)
The APC cache can significantly improve your PHP script performance, just by installing it, which basically takes 5 minutes! (Plus, it’s actually supported by the core PHP developers and will probably be integrated into PHP6…)
Here’s what I did on my Debian Lenny box…
First you may want to have a reference benchmark to see if it actually improves:
Code
ab -c5 -n100 http://www.yoursite.com/yourscript.php |
Now install the APC package:
Code
aptitude install php-apc |
Now, restart apache:
Code
/etc/init.d/apache2 restart |
Now, you can run your benchmark again and see the difference! Tada! :)