I noticed a note in the PHP documentation about speed differences between array_shift() (pulling the first element off the array) and array_reverse() followed by array_pop() (resulting in the same data, but got to by pulling the last element off the array).
Since I was working on some code to convert URL pieces to program arguments (like turning /admin/users/1/edit into section=admin, module=users, id=1, action=edit – stuff we tend to do every day) I thought I would take a look at the speed differences since I have always used array_shift() for this (after turning the string into an array via explode()).
My initial tests showed that array_shift was much faster than array_reverse followed by array_pop, and I wondered why someone would say that in the first place. But then I thought about it for a bit. When using array_shift the entire remaining array has to be re-indexed every call. For a very short array (like the one I was using) this is negligible. When you start looking at much larger arrays, however, this overhead adds up quickly.
To find out roughly where the break-even point on these two methods lie I whipped up a quick script to run with arrays sized from 10^1 values up to 10^5 values. What I found is that at less than 100 values you are not really gaining much (if anything) by using array_reverse and array_pop versus array_shift. Once you get to the 1000 value array size, however, the differences really add up (as you can see in the logarithmic scaling of the chart below).
The code I used to generate the numbers (which are shown in the chart as averages over 3 runs, rounded to the nearest millionth of a second) is:
<?php $counts = array(10,100,1000,10000,100000); foreach ($counts as $len) { $m2 = $m1 = array(); $x = 1; while ($x <= $len) { $m2[] = $m1[] = $x; $x++; } echo "Timing with array_shift() for $len items\n"; echo "000000"; $s1 = microtime(true); while (!empty($m1)) { $tmp = array_shift($m1); if ($tmp % 10 == 0) { echo chr(8),chr(8),chr(8),chr(8),chr(8),chr(8); echo str_pad(''.$tmp,6,'0',STR_PAD_LEFT); } } $s2 = microtime(true); echo "\nTook ",$s2 - $s1," seconds\n"; echo "Timing with array_reverse and array_pop() for $len items\n"; $s1 = microtime(true); $m2 = array_reverse($m2); while (!empty($m2)) { $tmp = array_pop($m2); if ($tmp % 10 == 0) { echo chr(8),chr(8),chr(8),chr(8),chr(8),chr(8); echo str_pad(''.$tmp,6,'0',STR_PAD_LEFT); } } $s2 = microtime(true); echo "\nTook ",$s2 - $s1," seconds\n"; echo "\n"; } ?>