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; }