Reputation: 535
Is there any kind of performance or other difference between following two cases of accessing a global variable in a closure:
Case 1:
$closure = function() use ($global_variable) {
// Use $global_variable to do something.
}
Case 2:
$closure = function() {
global $global_variable;
// Use $global_variable to do something.
}
Upvotes: 7
Views: 2436
Reputation: 1851
Your title question has been well answered, so I'll skip that.
You pose a different question in the body though. Which has better performance?
I made a simple test that I tried in PHP Sandbox:
<?php
$bool = true;
$one = function() use ($bool) {
return $bool;
};
$two = function() {
global $bool;
return $bool;
};
for ($power = 1; $power <= 10000000; $power *= 10) {
echo "loops = {$power}\n";
$before = microtime(true);
for ($i=0 ; $i<20000 ; $i++)
$one();
$after = microtime(true);
$timeOne = ($after-$before)/$i;
echo "{$timeOne} sec/one\n";
$before = microtime(true);
for ($i=0 ; $i<20000 ; $i++)
$two();
$after = microtime(true);
$timeTwo = ($after-$before)/$i;
echo "{$timeTwo} sec/two\n";
echo "Winner: " . ($timeOne > $timeTwo ? 'one' : 'two') . "\n\n";
}
And the results are very inconclusive:
loops = 1
6.2644481658936E-8 sec/one
5.6242942810059E-8 sec/two
Winner: one
loops = 10
5.4049491882324E-8 sec/one
4.9102306365967E-8 sec/two
Winner: one
loops = 100
5.1343441009521E-8 sec/one
5.4597854614258E-8 sec/two
Winner: two
loops = 1000
5.5849552154541E-8 sec/one
5.2559375762939E-8 sec/two
Winner: one
loops = 10000
5.6040287017822E-8 sec/one
5.3608417510986E-8 sec/two
Winner: one
loops = 100000
5.8901309967041E-8 sec/one
4.960298538208E-8 sec/two
Winner: one
loops = 1000000
6.2298774719238E-8 sec/one
6.9999694824219E-8 sec/two
Winner: two
loops = 10000000
8.3756446838379E-8 sec/one
5.9354305267334E-8 sec/two
Winner: one
Perhaps use
if a bit faster than global
, but you probably should make the decision on which to use based on that. It's all about the use-case (no pun intended).
You have more control with use
which is parent-scoped, so it's probably your best bet in most cases, but if you really need a variable from global scope, the answer is obvious.
Also note, that you can use use
with anonymous (lambda) functions only (like in my testing example). If you want to have the same functionality in normally defined functions, then you need to have the variable in question as function parameter, but referenced by pointer. Beware, it's not without caveat. If your function makes any changes to the referenced variable, these change won't be local to the function. Here's an example.
// ...
function three(&$var) {
return $var;
}
Upvotes: 0
Reputation: 2946
There is an important difference between your two examples:
$global_variable = 1;
$closure = function() use ($global_variable) {
return $global_variable;
};
$closure2 = function() {
global $global_variable;
return $global_variable;
};
$global_variable = 99;
echo $closure(); // this will show 1
echo $closure2(); // this will show 99
use
takes the value of $global_variable
during the definition of the closure while global
takes the current value of $global_variable
during execution.
global
inherits variables from the global scope while use
inherits them from the parent scope.
Upvotes: 24
Reputation: 217
Use
keyword are in parent scope, while global
and $GLOBALS
are from everywhere.
That's mean if you use global
you may not know if the value have changed, from where by what and what is the kind of the change.
You have more control by using use
. So it depends on your needs.
Upvotes: 1