Is while faster than foreach in core?

robertDouglass - August 11, 2006 - 17:06
Project:Drupal
Version:x.y.z
Component:base system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:won't fix
Description

Description

I recently read this:

foreach is convenient, but doing a while(list($key, $value) = each($var)) is way faster and less memory intensive because foreach makes a copy of the array before it cycles where each just moves the pointer

A colleague seemed to confirm in tests that this was the case. So I set out to test the theory in core. Here is a patch that replaces almost every single foreach with while for all of the files in includes.

I tried to test on my localmachine with ab, but it wasn't cooperating. If someone else could do some benchmarking on this patch, it'd be appreciated. Testing different pages (like admin/user/access) is important.

And if anyone has any tips on getting ab working with MAMP, drop me a line.

AttachmentSize
while.patch48.48 KB

#1

deekayen - August 11, 2006 - 17:42

Here's a demo script of the difference between foreach and while,list,each. Change the comment on lines 119 and 120 when you run it.

There is one big catch to look for when you change away from foreach - reset()ing the array pointer before you read the array again. Since foreach copies the array before looping, you don't have to worry about the array pointer.

AttachmentSize
test4.php.txt9.18 KB

#2

robertDouglass - August 11, 2006 - 17:50

http://de2.php.net/manual/en/control-structures.while.php#35022

This comment seems to show that the real truth is somewhat subtler and will take more thought than just replacing all foreach loops with while.

#3

robertDouglass - August 11, 2006 - 17:51

And based on these benchmarks, it would seem that while is in fact a step backwards:
http://byster.net/?page_id=48

#4

robertDouglass - August 11, 2006 - 17:54

Interestingly, according to those same benchmarks, sizeof is faster than count in PHP5:
http://byster.net/?page_id=48#a7

#5

deekayen - August 11, 2006 - 17:58

Re #4, I'm skeptical about that since sizeof is supposed to be an alias to count.

#6

deekayen - August 11, 2006 - 18:18

On something like this:

function drupal_map_assoc($array, $function = NULL) {
   if (!isset($function)) {
     $result = array();
-    foreach ($array as $value) {
+    while (list($value) = each($array)) {

That implemenation of list() is only correct if the key and value are the same, otherwise $value would actually have the value of the array's key because each() returns an array of the key as a value and the value as a value.

#7

killes@www.drop.org - August 13, 2006 - 13:05

I've run a patch through ab that has this change in menu.inc and didn't see any obvious changes.

The patch (for 4.7) is attached.

AttachmentSize
menueach_47.patch.txt9.75 KB

#8

robertDouglass - August 13, 2006 - 13:15
Status:patch (code needs work)» won't fix

I think our optimization efforts are better spent elsewhere. Closing. Thanks for testing, killes.

 
 

Drupal is a registered trademark of Dries Buytaert.