As I’ve mentioned in previous entries I’ve been migrating from an old Linux box to a new Windows server. I have a friend who I’ve been hosting on my server from some time. I finally kicked him in the butt and made him move his site to the new server, which is where the weirdness began.
First off, his site was being migrated from Linux/Apache/PostgreSQL/PHP to Windows/IIS/MySQL/PHP. The old Linux server paled in comparison to the new Windows server. We expected to see execution times drop on his application. However, in many cases they got worse!
Here were the symptoms:
The site “felt” fine when you were using it. There was no perceptible difference when using the site on the new server or the old server. However, the site has an execution timer which outputs the time it took to process the page. The times on the new server were not really bad, but in many cases were worse than what we saw on the old server. The strangest thing about the execution times was that they seemed to vary by connection.
In other words, users further away from the server or on slower connections were seeing longer processing times! As an example, I hopped on the server console and pulled up the site. I believe the execution time was something on the order of 0.018 seconds. However, someone 500 miles away from the server was seeing 0.5 seconds. I was seeing 0.1 seconds. All of these times were on the same page, with the only different being the computer the site was being requested from.
We spent quite a bit of time trying to track this one down. It turned out that the problem was due to PHP having output buffering shut off. This resulting in the time it took the server to successfully transmit output to the client was being tacked onto the execution time.
Think about it this way. When you make an http request it is sent to a web server, in this case IIS. IIS then hands the request off to PHP for processing. PHP proceeds to process some logic. It then outputs some data. After than it processes some more logic and then outputs more data. This is repeated until all processing is completed at which point IIS drops the connection to the client.
From ColdFusion I’m used to the wonders of the output buffer. However, in this particular circumstance PHP was not buffering the output. The lack of a buffer meant that each output was being passed onto IIS which handed it right to the client. Because this output was happening as the page was being processed it was adding to the entire time it took to process the page. Faster connections received the data faster and therefore had lower execution times. Slower connections had slower execution times.
It turns out that there’s a setting to turn output buffering on in PHP. To turn it on simply edit your php.ini file and make sure that output_buffering is set to true. In my case it was set to false. By enabling this PHP will write all output into a buffer in memory while the page is processing. Once all processing is completed the buffer will be flushed to IIS which will output it to the client. Because PHP doesn’t need to wait for the output to happen inline, PHP code can execute much faster.
After enabling output buffering all page execution times dropped down to approximately 0.018 seconds. The site now screams and is much faster than it was on the hold hardware.