A PHP Weakness: The Slowness of Echo
Posted by: Greg Bulmash in Techno Thoughts, Web ProgrammingSo, I was working on a project that generates a form based on a selection of items from a database, and the form could get pretty long. For performance testing I timed the execution of the script and found some very odd results. If the number of items on the list was 16 or thereabouts, the execution was about 5-7 one-thousands of a second. If the number of the items on the list was 50 (the maximum displayed on a page), the execution time was around 100 times longer.
I was stumped, how did increasing the number of items in the list by a factor of around 3 increase the execution time by a factor of 100?
I initially thought it was the database query. If the list was 16 items, that was the maximum number returned for the query. If the list was 50 items, it might have been the first 50 out of 300, which required extra sorting and organizing. But the database queries were timing out at close to the same speed.
I checked the processing of the data. Perhaps there was some bottleneck in my code that I could isolate. But as I broke the script down into smaller and smaller pieces, I found that all the parts that created the dynamically generated page were working fine up until I echoed the string that sent the compiled page to the user...
echo $page;
It was that line that took a couple of thousandths of a second when there were 16 questions, but took two or three hundred times longer when you tripled the length of $page. In fact, the tipping point was really between 19 and 20 questions. At 19 questions, it was executing in around 0.0085 seconds. At 20 questions, the execution time jumped to 0.27 seconds. Adding just one question caused the script to take 30 times longer to execute.
I Googled the topic and found that this is a well-known weakness of PHP. And, as a matter of fact, output in general is a weakness of PHP, because even knowing about this, people have long argued about whether it's faster to use "print" or "echo".
There were a number of suggestions on how to compensate, such as ob_start() and ob_flush to use output buffering with more fine grained control, but that wasn't doing the trick for me. Another suggested breaking the output string into chunks and outputting them individually in sequence. That also didn't work... at least not with his value of 8192 (8 kilobytes) as a chunk size. So I tried larger chunks (48 kilobytes, since that seemed to be the upper limit before slowing occurred) and smaller chunks (256 bytes, getting real small), but those weren't working. I was about ready to give up when I decided on one more try. I tried 2048 (2 kilobytes) and things finally sped up, and it seemed the best speed came from a 1-kilobyte chunk size.
So, if you find a PHP script is running really slow, the culprit might be something as simple as "echo $string" and the only way to fix it is to performance tune the output of that string. Amazing, huh?

Entries (RSS)
How large was the eventual page that was outputted? I tried to replicate this type of effect, with no success.
I tried a bunch of variations of large echos (lots of echos, one echo with lots of string concatenation, one really long echo), and the execution time always seemed to grow slowly and linearly - no big jump in execution time like you saw.
The biggest echo I tried was approx. 50kb of plain text (Lorem Ipsum text), and that didn't take long to execute at all. I also tried some with 50 smaller echos and a large echo with ~50 string concatenations.
Brian: The eventual pages were between 140 to 150k of HTML and text (or that was the length of the page string returned by the script along with the time to execute stats).
50k of HTML and text or thereabouts tended to be the tipping point. Try upping it to 60 or 70k and make sure it's being output in a page being accessed in a browser via the Internet. Based on the stuff I read, you may have more trouble reproducing if you're outputting the text to stdout or accessing the page locally.
Ahh, ok, now I've got it. When you were talking about 19 vs 20 questions, I didn't realize the files were so big.
However I noticed something else while doing this. I took the same amount of HTML (~110kb), took it out of the php tags, and had it printed as regular HTML (rather than being echo'ed). The script still took the same amount of time (~0.26 seconds) to process it... even though it wasn't being funneled through an echo call.
So, unless PHP defaults to echo'ing all content not located in the php tags, I'm not sure if this problem can be pegged to "echo" in particular. Although it is a good sign that our HTML files should be less than 100kb =)