I had made a decision to use closures for my callbacks instead of create_function and as such only support PHP > 5.3 mostly due to the increased debugability and also because I assumed (what is it they say about assumption?) that the overhead of the on-the-fly compilation of the create_function in my situation would probably offset any extra comparisons and such that had to be made within in the function.
This may well still be the case (for my application) and further testing is required, but I was interested in the output of this (very) simple test, that shows the create_function method being more than twice as fast as the closure when it can remove just four conditionals (and concats). Obviously there is no extra processing going on in my test case, and that is where most of the speed will be gained or lost, but in the case where you have little extra processing but a lot of conditionals (that could be removed) and the callback is called enough times I started to think that it may be better to use create_function.
However with the obvious similarity between create_function and eval, I’m wary of it.
So the main question is what are the differences between anonymous functions created with create_function and those of closures?
A few specific questions I’m thinking of are, will create_function even work when eval functionality is disabled? And, I’m sure I read somewhere recently that create_function functions will pollute the global (or class) namespace even if declared as inner functions, but closures won’t. I can’t find the reference to this now, but are either or both of those statements true?
This is the little test I ran:
<?php
function foo($a=true, $b=true, $c=true, $d=true)
{
$inner1 = create_function(
'',
'$r = \''.($a ? 'a' : '').
($b ? 'b' : '').
($c ? 'c' : '').
($d ? 'd' : '').'\';
return $r;'
);
$inner2 = function() use ($a, $b, $c, $d)
{
$r = '';
if($a) { $r .= 'a'; }
if($b) { $r .= 'b'; }
if($c) { $r .= 'c'; }
if($d) { $r .= 'd'; };
return $r;
};
$time = microtime(true);
for ($x=0; $x<99999; ++$x)
{
$i1out = $inner1();
}
echo '1:'.(microtime(true)-$time).'<br>';
$time = microtime(true);
for ($x=0; $x<99999; ++$x)
{
$i2out = $inner2();
}
echo '2:'.(microtime(true)-$time).'<br>';
echo var_dump($i1out===$i2out).'<br>';
}
foo();
The construct
function() {..}is an anonymous function, and this feature is often implemented together with closures. Neithercreate_functionnor anonymous functions pollute the global namespace.Since anonymous functions can access surrounding variables (the closure part), they can, in theory, be slightly slower. On the other hand, if you’re using bytecode caching (and if you’re not, you are obviously not concerned about performance), I’d expect the “compilation” overhead of anonymous functions to be slightly slower.
However, it is extremely unlikely that the difference between anonymous functions and
create_functionis a source of performance problems. Therefore, I’d choose the more readable form of an anonymous function if you are so fortunate to have a target platform with php>5.3.