So this week I was asked the question on which was quicker in PHP – A for loop or a foreach loop. It turns out that my assertion that they were both about the same performance was about right. Here are my test results
jason@server:~/php$ php speedtest.php
Starting test: Test for loop data length=4000000
Mem: 795.63MiB Used
Peak Mem: 795.63MiB Used
[xxxxxxxxx ]
Results for test Test for loop data length=4000000
Min : 0.6085901260376
Max : 0.61222791671753
Mean : 0.6110053062439
StdDev: 0.00015155474344889
Mem: 795.63MiB Used
Peak Mem: 795.64MiB Used
Starting test: Test foreach loop data length=4000000
Mem: 795.63MiB Used
Peak Mem: 795.64MiB Used
[xxxxxxxxx ]
Results for test Test foreach loop data length=4000000
Min : 0.41838312149048
Max : 0.42730903625488
Mean : 0.42159442901611
StdDev: 0.0010704358418783
Mem: 795.63MiB Used
Peak Mem: 795.64MiB Used
On average test 2 is faster than test 1 by 1.4493x
And the code I used to run the test is:
<?php
$data_length = 4000000;//rand(10000000,20000000);
for ($i=0; $i<$data_length; $i++) {
$data[] = $i;
}
$avg1 = run_test("Test for loop data length={$data_length}", "test_for",&$data);
$avg2 = run_test("Test foreach loop data length={$data_length}", "test_foreach",&$data);
print "On average ";
if ($avg1 < $avg2) {
print "test 1 is faster than test 2 by ";
printf("%0.4fx\n", $avg2 / $avg1);
} else {
print "test 2 is faster than test 1 by ";
printf("%0.4fx\n", $avg1 / $avg2);
}
function test_for(&$data) {
$max = count(&$data);
for($i=0; $i<$max; $i++) {$x=&$data[$i];}
}
function test_foreach(&$data) {
foreach ($data as &$x) {}
}
function run_test($name, $func, &$data) {
print "Starting test: $name\n";
printf(" Mem: %3.2fMiB Used\n", memory_get_usage()/1024/1024);
printf("Peak Mem: %3.2fMiB Used\n", memory_get_peak_usage()/1024/1024);
$num_runs = 10;
for($i=0; $i<$num_runs; $i++) {
print "[" . str_repeat('x',$i) . str_repeat(' ',$num_runs-$i) . "]\r";
$run_times[] = time_run($func,&$data);
}
print "\nResults for test {$name}\n";
$min = null;
$max = null;
$mean = null;
foreach ($run_times as $run_time) {
$mean += $run_time;
$max = (is_null($max) || $run_time > $max) ? $run_time : $max;
$min = (is_null($min) || $run_time < $min) ? $run_time : $min;
}
$mean /= $num_runs;
// now work out the std deviation aka confidence
$std_dev_count = 0;
foreach ($run_times as $run_time) {
$dev = $run_time - $mean;
$std_dev_count = $dev * $dev;
}
$std_dev = sqrt( $std_dev_count / ($num_runs-1));
print "Min : {$min}\n";
print "Max : {$max}\n";
print "Mean : {$mean}\n";
print "StdDev: {$std_dev}\n\n";
printf(" Mem: %3.2fMiB Used\n", memory_get_usage()/1024/1024);
printf("Peak Mem: %3.2fMiB Used\n", memory_get_peak_usage()/1024/1024);
return $mean;
}
function time_run($func,&$data) {
$start = microtime(1);
$func(&$data);
$end = microtime(1);
return $end - $start;
}