The other day we had a discussion on #drupal about the speed of various foreach constructs and webchick said I should blog this. First of all, let me give you a crash course on PHP references. Imagine variables values as drawers and names as labels on the drawers. One drawer can have more than one label and that's what we call a reference. So when you write $a = &$b
then PHP slaps a label on the drawer that holds the value of $a
. Now, if you unset($a)
then PHP removes the "a" label from the drawer, however the "b" label is still on it. When you unset($b);
too, then PHP marks the drawer empty as there is no way in the future to find this particular drawer. When you do $a = $b
then PHP will not immediately open a new drawer for b
and copy the contents from a
there, instead puts another kind of label on the drawer of a
. If you modify a variable which has this kind of label then at the time of modification the variable will be copied to a new drawer.
When you do a foreach ($array as $k => $v)
and in the loop you modify every $v
then PHP eventually needs to copy the whole array. On the other hand, if you foreach (array_keys($array) as $k)
and modify $array[$k]
then PHP does not need to copy the whole array. However, it needs to iterate the array twice, first to collect the array keys, second in the foreach. Finally, with PHP5 you can do foreach ($array as $k => &$v)
and if you modify $v
now then no copying occurs so this is indeed the fastest. Of course, if you do not want to modify the original array, then this trick can't be used.
Commenting on this Story is closed.
while (list($key, $value) = each($array)) {
//
}
reset($array);
list() is a language construct, therefore not subject to the same overhead as a normal function.