PHP Benchmarks
It's a long article, would you like to skip down?- Results
- Postincrement vs. Pretincrement
- Loop limit definition placement
- Str_replace vs. Strtr
- Switch vs. Elseif
- Single switch vs. Single if
- Single quotes vs. Double quotes
- GET/POST vs. REQUEST
- Equal check vs. Identical check
- While vs. For
- For vs. Foreach
- Foreach vs. While/List
- Absolute path vs. Relative path
- Conclusions
I was a little uneasy about the results at some of the "benchmark" sites I'd seen. That's why I wrote this page—my own php benchmark.
To start the benchmark project I wrote a comparison function that would test any two commands against each other to see which on was fastest. By default I set the function to run each command through a loop 1,000 times and do that 20 times each to get a relative average and margin of error. The function randomly decides which code to test first in case one test were to influence the other.
After doing many test I found that one thousand iterations for the inside loop resulted in the lowest margin of error. Twenty runs through each loop was also quite sufficient to gather all necessary data.
My function calculates the average speed of a command by adding all twenty benchmarks together then dividing by twenty. It calculates the margin of error as the average variance between the average speed and all the speeds taken. Note that the margin is an absolute value so the speeds themselves can be higher or lower than the average.
To download a copy of the source code that generates the live results page and inputs the data into the database, click here.
Some important considerations include the fact that I employ many optimization features on my server such as the Alternative PHP Cache and Zend. Because some of the optimizations I take effect all my programs, these benchmarks are likely effected. That means this is a great test for me, but the results may vary for you. I should also mention that I'm currently running PHP version 5.2.6.
The final thing my function does is add the value of each benchmark to a database. The results you see on this page are from that database. The reason for this is that running all the benchmarks takes around 53 seconds, and because of my output caching I can't send the page to you until all of the benchmarks are finished. That means you would have to wait 53 seconds at a blank screen hoping it would eventually load. Instead I simply display the stored results and give you the option to run the benchmarks and see the live results in another window by clicking . I encourage everyone to click that link before proceeding. Doing so contributes to the data and gives you a chance to see live results. Besides, you'll be busy reading while the page is loading.
*Note that the counting variable $i exists for all the programs. $i is used to control how many times the test is run, so it goes from 0 to 1000 in each test.
Postincrement
<?php
while($i<1000)
{
$i++;
}
?>
0.00429536347368421µs
VS.
Preincrement
<?php
while($i<1000)
{
++$i;
}
?>
0.00395169252631579µs
Preincrementing is 8.7% faster than Postincrementing by an average of 0.00034367094736842µs.
Note that $i++ and ++$i are not the same thing. Where the plus signs are relative to the variable establishes when the incrementing will happen. If all you are doing is bumping a variable by one then the two commands are analogous. Check out the official page at http://us3.php.net/manual/en/language.operators.increment.php if you are still unsure what the difference is.
Echo
<?php
echo "<!---->";
?>
0.00802478863157895µs
VS.
Print
<?php
print "<!---->";
?>
0.00805452µs
Echo is 0.37% faster than Print by an average of 2.973136842105E-5µs.
Defined in
<?php
$i=0;
$tmp='';
while($i<10000)
{
$tmp.='a';
++$i;
}
$test = array_fill(100000000000000000000000, 100, $tmp);
for($a=0; $a<count($test); $a++){}
?>
0.107274985263158µs
VS.
Defined first
<?php
$i=0;
$tmp='';
while($i<10000)
{
$tmp.='a';
++$i;
}
$test = array_fill(100000000000000000000000, 100, $tmp);
$size=count($test);
for($a=0; $a<$size; $a++){}
?>
0.0635217389473684µs
Defining the loop limit before the declaration is 68.88% faster than Defining the loop limit in the declaration by an average of 0.04375324631579µs.
str_replace
<?php
$bodytag = str_replace("%body%", "black", "<body text=%body%>");
?>
0.0176513636842105µs
VS.
strtr
<?php
$bodytag = strtr("<body text=%body%>","%body%", "black");
?>
0.0174004617894737µs
strtr is 1.44% faster than str_replace by an average of 0.0002509018947368µs.
Switch
<?php
switch($i)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
default:
}
?>
0.024697507368421µs
VS.
Elseif
<?php
if($i==0)
{}
elseif($i==1)
{}
elseif($i==2)
{}
elseif($i==3)
{}
elseif($i==4)
{}
elseif($i==5)
{}
elseif($i==6)
{}
elseif($i==7)
{}
elseif($i==8)
{}
elseif($i==9)
{}
else
{}
?>
0.0335001578947368µs
Switch is 35.64% faster than Elseif by an average of 0.0088026505263158µs.
Single switch
<?php
switch($i)
{
case 0:
break;
}
?>
0.0117451208955224µs
VS.
Single if
<?php
if($i==0)
{}
?>
0.00965806850746268µs
Single if is 21.61% faster than Single switch by an average of 0.0020870523880597µs.
Single quotes
<?php
$text='das;lfkjasd;lfkjads;lfkjasdl;fkjasdgnafdgljadhsfl;kadsfmasdl;gjkasdfio;mads;klgads;lfgkjads;fkljagl;k';
?>
0.00881191442105263µs
VS.
Double quotes
<?php
$text="das;lfkjasd;lfkjads;lfkjasdl;fkjasdgnafdgljadhsfl;kadsfmasdl;gjkasdfio;mads;klgads;lfgkjads;fkljagl;k";
?>
0.00856357042105264µs
Double quotes is 2.9% faster than Single quotes by an average of 0.00024834399999999µs.
Concatenation
<?php
$text=$i."das;lfkjasd;lfkjads;lfkjasdl;fkjasdgnafdgljadhsfl;kadsfmasdl;gjkasdfio;mads;klgads;lfgkjads;fkljagl;k";
?>
0.0104057157894737µs
VS.
Variable replacement
<?php
$text="{$i}das;lfkjasd;lfkjads;lfkjasdl;fkjasdgnafdgljadhsfl;kadsfmasdl;gjkasdfio;mads;klgads;lfgkjads;fkljagl;k";
?>
0.0114458424210526µs
Concatenation is 10% faster than Variable replacement by an average of 0.0010401266315789µs.
Single quotes concatenation
<?php
$text=$i.'das;lfkjasd;lfkjads;lfkjasdl;fkjasdgnafdgljadhsfl;kadsfmasdl;gjkasdfio;mads;klgads;lfgkjads;fkljagl;k';
?>
0.010435562µs
VS.
Double quotes concatenation
<?php
$text=$i."das;lfkjasd;lfkjads;lfkjasdl;fkjasdgnafdgljadhsfl;kadsfmasdl;gjkasdfio;mads;klgads;lfgkjads;fkljagl;k";
?>
0.0110032095789474µs
Single quotes concatenation is 5.44% faster than Double quotes concatenation by an average of 0.0005676475789474µs.
GET
<?php
$send=$_GET['sent'];
?>
0.0106061367368421µs
VS.
REQUEST
<?php
$send=$_REQUEST['sent'];
?>
0.0109076578947368µs
GET is 2.84% faster than REQUEST by an average of 0.0003015211578947µs.
POST
<?php
$send=$_POST['received'];
?>
0.011225774µs
VS.
REQUEST
<?php
$send=$_REQUEST['received'];
?>
0.0115952172631579µs
POST is 3.29% faster than REQUEST by an average of 0.0003694432631579µs.
Equal check
<?php
if($i==0){}
elseif($i==1){}
elseif($i==2){}
elseif($i==3){}
elseif($i==4){}
elseif($i==5){}
elseif($i==6){}
elseif($i==7){}
elseif($i==8){}
elseif($i==9){}
else{}
?>
0.0324484557894737µs
VS.
Identical check
<?php
if($i===0){}
elseif($i===1){}
elseif($i===2){}
elseif($i===3){}
elseif($i===4){}
elseif($i===5){}
elseif($i===6){}
elseif($i===7){}
elseif($i===8){}
elseif($i===9){}
else{}
?>
0.0338546368421053µs
Equal check is 4.33% faster than Identical check by an average of 0.0014061810526316µs.
While
<?php
$a=0;
while($a<1000)
{
$a++;
}
?>
0.116510463157895µs
VS.
For
<?php
for($a=0; $a<1000; $a++)
{}
?>
0.139472328421053µs
While is 19.71% faster than For by an average of 0.022961865263158µs.
For
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
$keys=array_keys($test);
$size=sizeOf($keys);
for($a=0; $a<$size; $a++)
{
$t=$test[$keys[$a]];
}
?>
0.0583986610526316µs
VS.
Foreach
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
foreach($test as $t){}
?>
0.0242028168421053µs
Foreach is 141.29% faster than For by an average of 0.034195844210526µs.
Foreach
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
foreach($test as $t){}
?>
0.0274258557894737µs
VS.
While/List
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
while(list(,$t) = each($test){}
?>
0.0471660389473684µs
Foreach is 71.98% faster than While/List by an average of 0.019740183157895µs.
Foreach + Keys
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
foreach($test as $k=>$t){}
?>
0.0309873873684211µs
VS.
While/List + Keys
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
while(list($k,$t) = each($test)){}
?>
0.0510786694736842µs
Foreach + Keys is 64.84% faster than While/List + Keys by an average of 0.020091282105263µs.
Foreach + reset
<?php
if(isset($test))
{
reset($test);
}
else
{
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
}
foreach($test as $t){}
?>
0.0300903926315789µs
VS.
While + reset
<?php
if(isset($test))
{
reset($test);
}
else
{
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
}
while(list(,$t) = each($test)){}
?>
0.051358332631579µs
Foreach + reset is 70.68% faster than While + reset by an average of 0.02126794µs.
Foreach + keys + reset
<?php
if(isset($test))
{
reset($test);
}
else
{
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
}
foreach($test as $k=>$t){}
?>
0.0365348694736842µs
VS.
While/list + keys + reset
<?php
if(isset($test))
{
reset($test);
}
else
{
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
}
while(list($k,$t) = each($test)){}
?>
0.0569643684210526µs
Foreach + keys + reset is 55.92% faster than While/list + keys + reset by an average of 0.020429498947368µs.
Foreach + keys
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
foreach($test as $k=>$t){}
?>
0.0294858136842105µs
VS.
Foreach + keys + reset
<?php
if(isset($test))
{
reset($test);
}
else
{
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
}
foreach($test as $k=>$t){}
?>
0.0367737810526316µs
Foreach + keys is 24.72% faster than Foreach + keys + reset by an average of 0.0072879673684211µs.
While/list + keys
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
while(list($k,$t) = each($test)){}
?>
0.0553698305263158µs
VS.
While/list + keys + reset
<?php
if(isset($test))
{
reset($test);
}
else
{
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
}
while(list($k,$t) = each($test)){}
?>
0.0493654221052631µs
While/list + keys + reset is 12.16% faster than While/list + keys by an average of 0.0060044084210527µs.
Modify foreach + keys
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
foreach($test as $k=>$t)
{
$test[$k].="a";
}
?>
0.0388301473684211µs
VS.
Modify while/list + keys
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
while(list($k,$t) = each($test))
{
$test[$k].="a";
}
?>
0.0556520168421053µs
Modify foreach + keys is 43.32% faster than Modify while/list + keys by an average of 0.016821869473684µs.
Foreach: complex
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
foreach($test as $t){}
?>
0.0194214778947368µs
VS.
While/list: complex
<?php
$test=array(1=>"cat","dog"=>0,"red"=>"green",5=>4,3,"me");
while(list(,$t) = each($test)){}
?>
0.0382576736842105µs
Foreach: complex is 96.99% faster than While/list: complex by an average of 0.018836195789474µs.
Foreach: simple
<?php
$test=array(1,1,1,1,1,1);
foreach($test as $t){}
?>
0.0211021221052632µs
VS.
While/list: simple
<?php
$test=array(1,1,1,1,1,1);
while(list(,$t) = each($test)){}
?>
0.0391599452631579µs
Foreach: simple is 85.57% faster than While/list: simple by an average of 0.018057823157895µs.
Foreach: long
<?php
$i=0;
$tmp='';
while($i<10000)
{
$tmp.='a';
++$i;
}
$test = array_fill(100000000000000000000000, 100, $tmp);
foreach($test as $t){}
?>
0.0559376768421053µs
VS.
While/list: long
<?php
$i=0;
$tmp='';
while($i<10000)
{
$tmp.='a';
++$i;
}
$test = array_fill(100000000000000000000000, 100, $tmp);
while(list(,$t) = each($test)){}
?>
0.247734726315789µs
Foreach: long is 342.88% faster than While/list: long by an average of 0.19179704947368µs.
Foreach: short
<?php
$test=array(1);
foreach($test as $t){}
?>
0.0198947804210526µs
VS.
While/list: short
<?php
$test=array(1);
while(list(,$t) = each($test)){}
?>
0.0287336536842105µs
Foreach: short is 44.43% faster than While/list: short by an average of 0.0088388732631579µs.
Absolute path
<?php
include("./empty.php");
?>
0.0751562564516129µs
VS.
Relative path
<?php
include("empty.php");
?>
0.0612573290322581µs
Relative path is 22.69% faster than Absolute path by an average of 0.013898927419355µs.
Unlike the results section, this part of the page isn't dynamic. That means that if all of a sudden the results dramatically change, the conclusions I've drawn from them won't change until I notice it. As such, if you happen to notice that one of my conclusions doesn't make any sense, feel free to shoot me an email saying so.
- Post incrementing is slightly faster than preincrementing—but they're not the same.
- Echo is just barely faster than print, but not quite as powerful.
- It's way better to define the loop limit before the loop rather than in it.
- Str_replace is slightly faster than strtr but I guess it takes longer to type...
- Switch is considerably faster than multiple elseifs, but they aren't even close to being the same thing. If you can use switch, go for it. Otherwise don't worry about it.
- Double and single quotes are about the same. Concatenation is quicker and safer than variable replacement, but not as convenient.
- GET—and POST to a lesser extent—are quicker than REQUEST, which I guess makes sense.
- Equal check is quicker than identical check. Again, they're not the same thing, but if you can use either one, stay with ==.
- While and for are each better for certain situations. Speed wise it doesn't make a lick of difference.
- Foreach is way faster than for but they aren't meant to be the same.
- Foreach is always faster than while(list). The longer the array, the more it shows.
- Resetting an array is detrimental to speed when used with foreach, but slightly beneficial when used with while.
At the bottom of the live results page is a table that shows how many times each command is used in my website—just the base page—and how much time I would save by using the efficient version over the inefficient. It then shows how much time I would save per page load, per day(at 200pages/day) and per year. For those of you who didn't see the live results I'll summarize it for you: making all the favorable changes would only save half a second at most of page generation time for every page viewed by every person on this site in a year combined.
That's leads me to what this page is about. Making small changes in the syntax of your code is hardly worth your time. Serverside optimizations like APC,CacheLite,Zend,Mod_GZip and others will save you way way more time than all the little code changes ever would. Also, logical errors often result in tons of lost time. If your page is doing things it doesn't need to be doing, you could be more than doubling your page load time.
A final thing that I'd like to point out is that coding efficiency and readability can often be way more important than these little changes. If it's going to take you an extra second to remember to use echo instead of print, it's better to just use print. While many tricks may speed up coding, an novice coder will have a harder time understanding
$i++;
over $i=$i+1;
So are these results totally useless? Of course not. They're great things to keep in mind and good to know if you are just learning to program in PHP. I wouldn't go back and change any code and I wouldn't spend a bunch of time studying these.