First of all, I understand in 90% of applications the performance difference is completely irrelevant, but I just need to know which is the faster construct. That and...
The information currently available on them on the net is confusing. A lot of people say foreach is bad, but technically it should be faster since it's suppose to simplify writing a array traversal using iterators. Iterators, which are again suppose to be faster, but in PHP are also apparently dead slow (or is this not a PHP thing?). I'm talking about the array functions: next() prev() reset() etc. well, if they are even functions and not one of those PHP language features that look like functions.
To narrow this down a little: I'm not interesting in traversing arrays in steps of anything more than 1 (no negative steps either, ie. reverse iteration). I'm also not interested in a traversal to and from arbitrary points, just 0 to length. I also don't see manipulating arrays with more than 1000 keys happening on a regular basis, but I do see a array being traversed multiple times in the logic of a application! Also as for operations, largely only string manipulation and echo'ing.
Here are few reference sites:
http://www.phpbench.com/
http://www.php.lt/benchmark/phpbench.php
What I hear everywhere:
foreach
is slow, and thus for
/while
is fasterforeach
copies the array it iterates over; to make it faster you need to use references$key = array_keys($aHash); $size = sizeOf($key);
for ($i=0; $i < $size; $i++)
is faster than a foreach
Here's my problem. I wrote this test script: http://pastebin.com/1ZgK07US and no matter how many times I run the script, I get something like this:
foreach 1.1438131332397
foreach (using reference) 1.2919359207153
for 1.4262869358063
foreach (hash table) 1.5696921348572
for (hash table) 2.4778981208801
In short:
foreach
is faster than foreach
with referenceforeach
is faster than for
foreach
is faster than for
for a hash tableCan someone explain?
PHP Version 5.3.0
Thank you everyone who tried to help.
I'll likely stick to foreach (the non-reference version) for any simple traversal.
My personal opinion is to use what makes sense in the context. Personally I almost never use for
for array traversal. I use it for other types of iteration, but foreach
is just too easy... The time difference is going to be minimal in most cases.
The big thing to watch for is:
for ($i = 0; $i < count($array); $i++) {
That's an expensive loop, since it calls count on every single iteration. So long as you're not doing that, I don't think it really matters...
As for the reference making a difference, PHP uses copy-on-write, so if you don't write to the array, there will be relatively little overhead while looping. However, if you start modifying the array within the array, that's where you'll start seeing differences between them (since one will need to copy the entire array, and the reference can just modify inline)...
As for the iterators, foreach
is equivalent to:
$it->rewind();
while ($it->valid()) {
$key = $it->key(); // If using the $key => $value syntax
$value = $it->current();
// Contents of loop in here
$it->next();
}
As far as there being faster ways to iterate, it really depends on the problem. But I really need to ask, why? I understand wanting to make things more efficient, but I think you're wasting your time for a micro-optimization. Remember, Premature Optimization Is The Root Of All Evil
...
Edit: Based upon the comment, I decided to do a quick benchmark run...
$a = array();
for ($i = 0; $i < 10000; $i++) {
$a[] = $i;
}
$start = microtime(true);
foreach ($a as $k => $v) {
$a[$k] = $v + 1;
}
echo "Completed in ", microtime(true) - $start, " Seconds\n";
$start = microtime(true);
foreach ($a as $k => &$v) {
$v = $v + 1;
}
echo "Completed in ", microtime(true) - $start, " Seconds\n";
$start = microtime(true);
foreach ($a as $k => $v) {}
echo "Completed in ", microtime(true) - $start, " Seconds\n";
$start = microtime(true);
foreach ($a as $k => &$v) {}
echo "Completed in ", microtime(true) - $start, " Seconds\n";
And the results:
Completed in 0.0073502063751221 Seconds
Completed in 0.0019769668579102 Seconds
Completed in 0.0011849403381348 Seconds
Completed in 0.00111985206604 Seconds
So if you're modifying the array in the loop, it's several times faster to use references...
And the overhead for just the reference is actually less than copying the array (this is on 5.3.2)... So it appears (on 5.3.2 at least) as if references are significantly faster...