Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP foreach function performance

Does anyone know if doing this

foreach ($user->getFriends() as $friend) {
  // Do something.
}

Causes PHP to call the function getFriends() on the user object multiple times and thus would this be more efficient?

$friends = $user->getFriends();
foreach ($friends as $f) {
 // Do something.
}
like image 320
Gcoop Avatar asked Oct 28 '10 13:10

Gcoop


3 Answers

foreach uses the result of the expression $user->getFriends(). You could look at it like this:

foreach (($user->getFriends()) as $friend) {
    // ...
}

The function is not going to be called more than once, since you pass its result and not the function itself. foreach does not know about the function.

like image 110
jwueller Avatar answered Oct 15 '22 13:10

jwueller


Here is a code to bench:

srand();
$asize = 1000000;
$a = array();
for ($x=1;$x<=$asize;$x++) $a[]=rand();


$i=0;
$s = microtime(true);
foreach($a as $k=>$v) {
    ++$a[$k];
}
$e = microtime(true);
dolog($s,$e,'FOREACH-KEY');

$i=0;
$s = microtime(true);
foreach($a as &$v) {
    ++$v;
}
$e = microtime(true);
dolog($s,$e, 'FOREACH-PTR');

$i=0;
$s = microtime(true);
for ($x=0;$x<$asize;$x++){
    ++$a[$x];
}
$e = microtime(true);
dolog($s,$e,'FOR');

function awpp(&$item,$key){
    ++$item;
}

$s = microtime(true);
array_walk($a, 'awpp');
$e = microtime(true);
dolog($s,$e,'ARRAY_WALK');

reset($a);
$s = microtime(true);
while (list($k, $v) = each($a)) {
    ++$a[$k];
}
$e = microtime(true);
dolog($s,$e,'EACH');

reset($a);
$s = microtime(true);
$node = current($a);
++$node;
while($node=next($a)) {
    ++$node;
}
$e = microtime(true);
dolog($s,$e,'NEXT');

And a result:

FOREACH-KEY Start: 1367595478.8087210655, End: 1367595479.2945981026, DIFF: 0.4858770370
FOREACH-PTR Start: 1367595479.2946701050, End: 1367595479.4266710281, DIFF: 0.1320009232
FOR Start:         1367595479.4267220497, End: 1367595479.6769850254, DIFF: 0.2502629757
ARRAY_WALK Start:  1367595479.6770300865, End: 1367595481.1930689812, DIFF: 1.5160388947
EACH Start:        1367595481.1931140423, End: 1367595482.5088000298, DIFF: 1.3156859875
NEXT Start:        1367595482.5088429451, End: 1367595483.2801001072, DIFF: 0.7712571621

So, the fastest is foreach with pointer and without key value.

like image 37
Igor Popov Avatar answered Oct 15 '22 15:10

Igor Popov


I don't think the getFriends() method in this case would be called multiple times.

foreach makes a copy of the array to iterate over, and then iterates over the copy. There's no reason to call your method more than once.

The copying itself (and the resulting use of memory) is what you should consider when using a foreach loop.

like image 25
Thomas Avatar answered Oct 15 '22 13:10

Thomas