A colleague brought up an interesting question today, he asked which was better performance-wise using closures or using capturing with output control (ob_start() / ob_get_clean()). I expected closures would be better since there's a bit more going on behind the scenes when using output buffering, but I wasn't sure so I decided to make a little test.
The not so scientific test
Keeping it simple, the case was creating output data and then echo'ing it. In our project we use output buffering in order to render multiple views, layouts and whatnot, so these tests should be seen as functions that would run from a view script using output buffering. If you just want to send the output directly to the browser then the comparison would be echo vs closures in which case an echo would be quicker since you don't add the overhead of calling a function.
Three scripts were made, one using a closure, 1 using "echo ob_end_clean()" and another using "ob_end_flush()".
// using closure
$time = microtime();
$closure = function()
{
$a = str_repeat("Hello", 4242);
echo $a;
};
$closure();
unset($closure);
$endtime = microtime();
echo "\n\n" . ($endtime - $time), ' - ', memory_get_peak_usage(), ' - ', memory_get_usage(), "\n";
// using ob_end_clean()
$time = microtime();
ob_start();
$a = str_repeat("Hello", 4242);
echo $a;
echo ob_get_clean();
$endtime = microtime();
echo "\n\n" . ($endtime - $time), ' - ', memory_get_peak_usage(), ' - ', memory_get_usage(), "\n";
// using ob_end_flush()
$time = microtime();
ob_start();
$a = str_repeat("Hello", 4242);
echo $a;
ob_end_flush();
$endtime = microtime();
echo "\n\n" . ($endtime - $time), ' - ', memory_get_peak_usage(), ' - ', memory_get_usage(), "\n";
I ran the tests using "php -q filename.php". I know I should have run the scripts through xdebug or something but I was lazy so instead I just measured microtime, memory usage and peak memory usage as reported by PHP. Results will vary naturally vary based on platform and PHP compile settings/flags. I ran the test on my laptop, a mac book pro 2.2 ghz core 2 duo, with the default OS X installation of PHP.
The result
I ran each script 5 times in a row without any PHP cache or similar.
The overall results were pretty much as expected in favor of closures. But in reality only the peak memory usage would be an issue. The difference in rendering time was minimal and I doubt that you'd ever run in to any issues because of it. Even when using ob_end_clean to move the buffer in to a variable before outputting it, the added memory increase was lower than I expected.
time - peak - mem 0.001673 - 709648 - 645984 (capturing #1, ob_end_clean ) 0.001406 - 688328 - 645880 (capturing #1, ob_end_flush) 0.001419 - 649288 - 625664 (closures #1) 0.001514 - 709648 - 645984 (capturing #2, ob_end_clean ) 0.00149 - 688328 - 645880 (capturing #2, ob_end_flush) 0.001515 - 649288 - 625664 (closures #2) 0.001524 - 709648 - 645984 (capturing #3, ob_end_clean ) 0.001217 - 688328 - 645880 (capturing #3, ob_end_flush) 0.001408 - 649288 - 625664 (closures #3) 0.001499 - 709648 - 645984 (capturing #4, ob_end_clean ) 0.001502 - 688328 - 645880 (capturing #4, ob_end_flush) 0.001454 - 649288 - 625664 (closures #4) 0.00104 - 709648 - 645984 (capturing #5, ob_end_clean ) 0.00148 - 688328 - 645880 (capturing #5, ob_end_flush) 0.001445 - 649288 - 625664 (closures #5)
The conclusion
So judging from this highly non scientific test my conclusion would be that in most cases it probably doesn't matter which you choose. Performance junkies should however use closures to keep memory waste to a minimum. But as with most things PHP, I guess it depends on the use case. If the case is a view script that will be handled by, designers / front-end developers / end users, rather than backend developers then I'd recommend capturing just because syntax is simpler and looks less intimidating for those not confident with PHP.
3 Responses to PHP: Capture vs Closures
Feed for this Entry3 Pingbacks
0 Comments