Comparing PHP array_shift to array_pop

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).

shift_vs_pop.jpg

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:

  1. <?php
  2. $counts = array(10,100,1000,10000,100000);
  3. foreach ($counts as $len)
  4. {
  5.         $m2 = $m1 = array();
  6.         $x = 1;
  7.         while ($x <= $len)
  8.         {
  9.                 $m2[] = $m1[] = $x;
  10.                 $x++;
  11.         }
  12.         echo "Timing with array_shift() for $len items\n";
  13.         echo "000000";
  14.         $s1 = microtime(true);
  15.         while (!empty($m1))
  16.         {
  17.                 $tmp = array_shift($m1);
  18.                 if ($tmp % 10 == 0)
  19.                 {
  20.                         echo chr(8),chr(8),chr(8),chr(8),chr(8),chr(8);
  21.                         echo str_pad(.$tmp,6,‘0′,STR_PAD_LEFT);
  22.                 }
  23.         }
  24.         $s2 = microtime(true);
  25.         echo "\nTook ",$s2$s1," seconds\n";
  26.        
  27.         echo "Timing with array_reverse and array_pop() for $len items\n";
  28.         $s1 = microtime(true);
  29.         $m2 = array_reverse($m2);
  30.         while (!empty($m2))
  31.         {
  32.                 $tmp = array_pop($m2);
  33.                 if ($tmp % 10 == 0)
  34.                 {
  35.                         echo chr(8),chr(8),chr(8),chr(8),chr(8),chr(8);
  36.                         echo str_pad(.$tmp,6,‘0′,STR_PAD_LEFT);
  37.                 }
  38.         }
  39.         $s2 = microtime(true);
  40.         echo "\nTook ",$s2$s1," seconds\n";
  41.         echo "\n";
  42. }
  43. ?>

Post to Twitter Post to Yahoo Buzz Buzz This Post Post to Delicious Delicious Post to Digg Digg This Post Post to Ping.fm Ping This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

No Responses so far »

Comment RSS · TrackBack URI

Say your words