[TYPO3-dev] FYI: comparing execution speed of some php functions

Jigal van Hemert jigal at xs4all.nl
Sat Jun 27 10:55:00 CEST 2009


Hi Myself ;-)

Jigal van Hemert wrote:
>> foreach() loop:
>> ---------------------------------------------
>> foreach() took                  11.16920 ms
>> foreach() with KEY took         12.35318 ms
>>
>> while(list()=each()) loop:
>> ---------------------------------------------
>> while(list()...) took           58.12597 ms
>> while(list()...) with key took  64.06283 ms
> 
> There is another difference between these two, see:
> http://www.php.net/manual/en/control-structures.foreach.php
> 
> Quote: "Note: Unless the array is referenced, foreach operates on a copy
> of the specified array and not the array itself. foreach  has some side
> effects on the array pointer. Don't rely on the array pointer during or
> after the foreach without resetting it. "

http://www.tuxradar.com/practicalphp/18/1/9 tells a different story:

Quote: "Furthermore, PHP makes extensive use of "copy-on-write", which 
means taking ten copies of the same array is also free, because they all 
point to the same object. It's called "copy-on-write" because the minute 
one of the arrays change from the others, a full copy is made so the 
change is kept separate."

Testing this gives very strange results:

Foreach loop
===================================
$a = 0;
$myarr2 = $myarr;
$first = true;
foreach ($myarr2 as $k => $v) {
   $v = 4 * 45;
   if ($first == true) {
     echo 'memory usage inside loop: ', memory_get_usage(), "\n";
     $first = false;
   }
}

while(list()) loop:
===================================
$a = 0;
$myarr2 = $myarr;
$first = true;
reset($myarr2);
while (list($t) = each($myarr2)) {
   $a = 4 * 45;
   if ($first == true) {
     echo 'memory usage inside loop: ', memory_get_usage(), "\n";
     $first = false;
   }
}

Foreach with reference to value (unmodified)
====================================
$a = 0;
$myarr2 = $myarr;
$first = true;
foreach ($myarr2 as $k => &$v) {
   $a = 4 * 45;
   if ($first == true) {
     echo 'memory usage inside loop: ', memory_get_usage(), "\n";
     $first = false;
   }
}

Foreach with reference to value (modified)
====================================
$a = 0;
$myarr2 = $myarr;
$first = true;
foreach ($myarr2 as $k => &$v) {
   $v = 4 * 45;
   if ($first == true) {
     echo 'memory usage inside loop: ', memory_get_usage(), "\n";
     $first = false;
   }
}

The numbers:

memory usage: 79264
fill an array with 100000 items:
---------------------------------------------
setting up array took 		69.16404 ms
memory usage: 7404532

[So the array takes up about 6.5MB]

foreach() loop:
---------------------------------------------
memory usage before: 7404532
memory usage inside loop: 12329060
foreach() with KEY took 	63.61604 ms
memory usage: 7468584

[According to tuxradar making a copy of an array should take up a 
substantial amount of memory, but inside the foreach loop PHP uses quite 
a bit more. The extra stuff is removed automatically when the loop ends.]

while(list()) loop:
---------------------------------------------
memory usage before: 7472512
memory usage inside loop: 12333504
while(list()) took 	159.44004 ms
memory usage: 12333560

[This was expected to be slow, but unexpectedly the loop also took a 
huge amount of memory. Even stranger, this memory hasn't been freed 
after the loop ended!]

foreach() with reference to value, no change to array loop:
---------------------------------------------
memory usage before: 7468532
memory usage inside loop: 12329092
foreach() with KEY + reference to value took 	61.81502 ms
memory usage: 14729132

[According to the manul a reference wouldn't require a copy of the array 
for foreach. Inside the loop a lot of memory has been taken. Even though 
the array hasn't been changed there is a copy present after the foreach 
ends. The copy-on-write feature has been triggered by the reference!?!?]


foreach() with reference to value, changing array loop:
---------------------------------------------
memory usage before: 7468512
memory usage inside loop: 12351652
foreach() with KEY + reference to value took 	56.69117 ms
memory usage: 14729160

[Not very much different than not changing the array, although the loop 
is slightly faster than the loop that doesn't change the variable. 
Apparently changing a simple variable outside the loop takes more time 
than changing the array. There is a copy left when the foreach ends like 
we expected.]

My conclusion:
Contrary to what we were taught in the era of PHP4 the foreach() loop 
doesn't take up more memory than the while() loop. Foreach is way faster 
than while and if you need to change the elements of the array use 
foreach with references to the value(s).
Loops take up a lot of memory any way you do them.

A copy of the code is for some time available at 
http://www.xs4all.nl/~dcbjht/typo3/looptest.txt

Regards,
-- 
Jigal van Hemert.




More information about the TYPO3-dev mailing list