PHP: Is Output Buffering Significantly Slower Than Strings?
Posted in Programming on August 8th, 2008 by Carl ZulaufI love PHP. I use it constantly for rapid prototyping and small scripts that help “glue” things together for me. However, one annoyance I have with PHP is related to building large strings. This isn’t particularly difficult in PHP… in fact its easier in PHP than most languages. The problem is that sometimes my entire page output will need to be contained in a string for various reasons (headers still need to be sent, the output needs to be passed to a filter or other function, etc…). Creating multi-line strings in PHP using single or double quotes looks awful, and the heredoc syntax prevents proper indentation. All of these methods also require tons of concatenation if any logic is necessary. Sometimes I have forgone these methods and instead used Output Buffering to prevent output from being sent, then I simply grab the content of the output buffer and store it in a string. This has several advantages, including ease of coding and the freedom of using the same code whether I need the output stored in a string or sent to the client immediately. However, its main disadvantage is that it is much slower… right? Well, I decided to find out exactly how much slower Output Buffering really is. Read on for my results.
First, lets start witch what output buffering looks like vs. using single quotes and double quotes.
Output Buffering example:
ob_start(); ?> <div class="resultset"> <div class="xResult">$x is set to <?php echo $x ?></div> <div class="yResult">$y is set to <?php echo $y ?></div> <div class="zResult">$z is set to <?php echo $z ?></div> </div> <?php $string = ob_end_clean();
Single Quotes example:
$string = ' <div class="resultset"> <div class="xResult">$x is set to ' . $x . '</div> <div class="yResult">$y is set to ' . $y . '</div> <div class="zResult">$z is set to ' . $z . '</div> </div> ';
Double Quotes example:
$string = " <div class=\"resultset\"> <div class=\"xResult\">\$x is set to $x</div> <div class=\"yResult\">\$y is set to $y</div> <div class=\"zResult\">\$z is set to $z</div> </div> ";
All of these methods should build a variable $string with content similar to the following:
<div class="resultset">
<div class="xResult">$x is set to 401</div>
<div class="yResult">$y is set to 73953</div>
<div class="zResult">$z is set to 3</div>
</div>
To determine how much slower output buffering is than the other two methods I wrote a benchmark (source code) which repeats each method a large number of times. The benchmark linked to here is hosted on a shared hosting server so the results are unlikely to be consistent. I used an Athlon XP 3200+ system with 1GB of RAM running Apache 2.2.8 and PHP 5.2.6 on Ubuntu 8.04. I made sure that the system was not doing anything but serving up this benchmark. The results were repeatable and consistent, and the following is an average of five separate benchmark runs.
| String Building Method | Execution Overhead % | ||
| Slower | Faster | Consecutive Test | Random Test |
| Output Buffering | Single Quotes | 13.4743% | 8.0886% |
| Output Buffering | Double Quotes | 16.0896% | 8.7876% |
| Single Quotes | Double Quotes | 2.3048% | 0.6467% |
As you can see, output buffering is clearly the slowest method. What is surprising, however, is that the difference is fairly small. The greatest delta exists between Output Buffering and Double Quotes, which just tops 16% when the tests are ran in consecutive mode. Even 16%, though, is not a huge performance difference. Its still small enough that using output buffering exclusively on a larger project for building large strings may not be considered a significant performance impact, and the advantages of using output buffering may make it the obvious choice.
Next, I decided to see if using logic while building strings would have any affect on the performance overhead output buffering incurs. In case what I am saying is not clear, here are a couple examples of using logic while building a string using both Output Buffering and Single Quotes:
// Output Buffering with Logic example: ob_start(); ?> <div class="resultset"> <div class="xResult">$x is set to <?php echo $x ?></div> <div class="yResult">$y is set to <?php echo $y ?></div> <div class="zResult">$z is set to <?php echo $z ?></div> <?php if ( $x < $z ): ?> <div class="LogicResult">$z is greater than $x by <?php echo ( $z - $x ) ?></div> <?php endif ?> </div> <?php $string ob_get_clean(); // Single Quotes with Logic example: $string = ' <div class="resultset"> <div class="xResult">$x is set to ' . $x . '</div> <div class="yResult">$y is set to ' . $y . '</div> <div class="zResult">$z is set to ' . $z . '</div>'; if ( $x < $z ) $string .= ' <div class="LogicResult">$z is greater than $x by ' . ( $z - $x ) . '</div>'; $string .= ' </div> ';
These examples further highlight the advantages of using Output Buffering. The code is clearly cleaner and easier to work with. With traditional string building (using single quotes, double quotes, or even heredoc) the string must be terminated, the conditional evaluated, possibly concatenating the string, then the string must be concatenated a final time to add additional closing string data. This is convoluted and ugly, and the performance difference would need to be immense for me to consider building strings like this using single quotes or double quotes. However, due to the additional string concatenation my hypothesis was that adding logic would actually lessen the performance overhead when using Output Buffering, making Output Buffering even more attractive. Lets have a look at what the actual results show when we add logic:
| String Building Method | Execution Overhead % | ||
| Slower | Faster | Consecutive Test | Random Test |
| Output Buffering | Single Quotes | 4.4925% | 2.2353% |
| Output Buffering | Double Quotes | 6.8601% | 3.5564% |
| Single Quotes | Double Quotes | 2.2659% | 1.2923% |
While I expected a reduction in the performance cost of output buffering, I was not anticipating a reduction of this magnitude which such a small amount of logic. Against single quotes, Output Buffering has reduced its performance disadvantage by approximately 2/3, and compared to double quotes the disadvantage has been reduced by well over 1/2! These results are very encouraging for those wishing to use Output Buffering. The results from adding a small amount of logic lead me to believe that the performance disadvantage of Output Buffering will continue to shrink as the size of the string and amount of logic increases. In fact, a large enough string or frequent enough use of logic may eliminate the performance disadvantage completely and could even give output buffering a performance advantage in certain situations.
In the end the most important part of this investigation for me is that I will be much more likely to use output buffering in the future.
Tags: Benchmarking, PHP
Hello,
Super post, Need to mark it on Digg
Have a nice day
Joker
Hello webmaster
I would like to share with you a link to your site
write me here preonrelt@mail.ru
Hi,
Thank you! I would now go on this blog every day!
Thanks
Charlie
Hello,
examancer.com – da best. Keep it going!
Have a nice day
Jinny
Hi there,
Amazing! Not clear for me, how offen you updating your examancer.com.
Thanks
GlenStef