A lot of those results were to be expected I suppose. However, my tests are a bit different. I'm not using the while(list()=each()) mechanism and within each iteration there is a sub-loop that's happening where the true differences between various constructs are being tested.
There was one big suprise, but perfectly understandable when you pull over and think about it for a sec. The length of the variable name has a huge effect on performance. I have two seperate tests using the array_keys()/for() loop construct, but one was made faster simply by reducing the lenghts of the names to something ridiculous and unmaintainable. But even doing that, foreach() with the '&' operator was still faster.
So yes, array_keys() does seem to be pretty fast, but not
faster so using it doesn't seem to make sense to me as there are just more hoops to jump through to set it up.
Code: Select all
<?php
class testObject
{
protected $y=0;
protected $z=0;
var $name='';
public function meth1($val)
{ $this->y=($val+1); }
public function meth2()
{ ++$this->z; }
public function meth3($val)
{ $this->name=$val; }
function reset()
{
$this->y=0;
$this->z=0;
}
}
# For some reason, calling this before getting started has a good effect on the performance
# of each subsequent call
getmicrotime();
$iters=1000000;
$num_arrays=4;
$list='jean_grey|rouge|storm|sprite|psylocke';
$girls=explode('|', $list);
$girls_size=count($girls);
$girl_objs=array();
for($x=0; $x<$girls_size; ++$x)
{
for($xx=0; $xx<$num_arrays; ++$xx)
{
$girl_objs1[$girls[$x]]=new testObject;
$girl_objs1[$girls[$x]]->name=$girls[$x];
$girl_objs2[$girls[$x]]=new testObject;
$girl_objs2[$girls[$x]]->name=$girls[$x];
$girl_objs3[$girls[$x]]=new testObject;
$girl_objs3[$girls[$x]]->name=$girls[$x];
$girl_objs4[$girls[$x]]=new testObject;
$girl_objs4[$girls[$x]]->name=$girls[$x];
}
}
reset($girls);
############################################################################
# Using the spl arrayIterator
############################################################################
$time_start=0;
$arrayObj = new arrayObject($girl_objs3);
$iterator=$arrayObj->getIterator();
$time_start=getmicrotime(); // Start the timer here
while($x<$iters)
{
$iterator->rewind();
while($iterator->valid())
{
$girl=$iterator->current();
$girl->meth1($x);
$girl->meth2();
$iterator->next();
}
++$x;
}
echo "Using the spl arrayIterator Ojbect took: " . number_format( ((getmicrotime()) - $time_start), 4) . " seconds.\n\n";
$time_start=0;
############################################################################
############################################################################
# Using the existing key list / array size generated while creating the array of objects
############################################################################
$q=&$girl_objs4;
$z=array_keys($girl_objs4);
$s=sizeof($z);
$time_start=getmicrotime(); // Start the timer here
$x=0;
while($x<$iters)
{
for($i=0; $i<$s; ++$i)
{
$q[$z[$i]]->meth1($x);
$q[$z[$i]]->meth2();
}
++$x;
}
echo "Using array keys and an alias with small var name sizes took: " . number_format( ((getmicrotime()) - $time_start), 4) . " seconds.\n\n";
$time_start=0;
############################################################################
############################################################################
# Using array keys. This is awkward anyways as the object array is essentially an associative array.
############################################################################
$gn=array_keys($girl_objs1);
$j=sizeof($gn);
$time_start=getmicrotime(); // Start the timer here
$x=0;
while($x<$iters)
{
for($i=0; $i<$j; ++$i)
{
$girl_objs1[$gn[$i]]->meth1($x);
$girl_objs1[$gn[$i]]->meth2();
}
++$x;
}
echo 'Using array_keys() took: ' . number_format( ((getmicrotime()) - $time_start), 4) . " seconds.\n\n";
$time_start=0;
############################################################################
############################################################################
# Using the plain jane foreach()
############################################################################
$time_start=getmicrotime(); // Start the timer here
$x=0;
while($x<$iters)
{
foreach($girl_objs2 as &$girl)
{
$girl->meth1($x);
$girl->meth2();
}
++$x;
}
echo 'Using foreach() with the \'&\' operator took: ' . number_format( ((getmicrotime()) - $time_start), 4) . " seconds.\n\n";
############################################################################
# Timing courtesy of
function getmicrotime()
{
list($usec, $sec) = explode(" ",microtime());
return ((float)$usec + (float)$sec);
}
function my_print_r($val)
{ echo '<pre>'; print_r($val); 'echo </pre>'; }
?>
I ran these tests on the command line using PHP 5.05. I know, it's old as dirt. I've been too busy writing code and working on my car to install 5.2, but I'll
get tht done soon enough.
If there are any problems that anyone can see in the code that has an effect on the performance, please try it or chime in. I've made mistakes in the past with this
stuff so it wouldn't be a first.
Cheers