Jump to content
MakeWebGames

Speed differences within PHP


a_bertrand

Recommended Posts

Some of you guys think there is huge difference between two things inside PHP like single quote or double quote, or print and echo, or whatever else. I tried to make some tests to show exactly how it affect or doesn't affect PHP and you may be surprised by some of the results. You will find first the results and then the full code I used, feel free to download it and test it on your computer (better from the command line instead of the browser).

For the lazy one, here is a short answer:

- Quote or Double quote nearly no difference (around 0.65%)

- Echo or Print nearly no difference (around 0.39%)

- String concatenation ("string a"."string b") or sprintf there is a difference (around 12%) sprintf is faster

- Speed difference between OO and procedural, there is a difference (around 31%) procedural is faster

- For or Foreach, there is a difference (around 46%) foreach is faster

- Inline or calling a function, there is a difference (around 29%) inline code is faster

My conclusions:

- Don't change quotes or double quotes, you will see no difference basically, use them when you need one or the other functionality.

- Don't replace your print or echo, you will see no difference, but use only one of the 2, not both... doesn't make sense.

- String concatenations... are not really working well. Better use a sprintf.

- OO is slower, no matter what you do (tested on PHP 5.3.5), yet you could end up with a cleaner code. So take OO if you want the features / clean separation of it, but don't expect to gain speed, you will actually lose some.

- Foreach loops are faster than for, so use them, however it doesn't make sense yet to run across your code to change them all, I doubt you will see any real difference while running your game.

- Inline code (avoid function call, and duplicate the code where you need it), is indeed faster, yet of course it make your code less readable. So don't use it, doesn't make any real difference for a web game, and it's better to have a readable code instead of some huge spaghetti code.

 

-------------------------------------------------------------
Checks the difference between single quote and double quote.
50,000,000 times in loop.
-------------------------------------------------------------
Testing single quote... 14.66 sec.
Testing double quote... 14.57 sec.
Difference: 0.65 %
-------------------------------------------------------------
Checks the difference between echo and print.
10,000,000 times in loop.
-------------------------------------------------------------
Testing echo function... 14.72 sec.
Testing print function... 14.77 sec.
Difference: 0.39 %
-------------------------------------------------------------
Checks the difference between concatenation and sprintf.
10,000,000 times in loop.
-------------------------------------------------------------
Testing concatenation... 10.43 sec.
Testing sprintf... 9.13 sec.
Difference: 12.46 %
-------------------------------------------------------------
Checks the difference between procedural and OO.
1,000 times in loop.
-------------------------------------------------------------
Testing procedural... 12.95 sec.
Testing OO... 18.8 sec.
Difference: 31.11 %
-------------------------------------------------------------
Checks the difference between for and foreach.
100,000 times for 1,000 in loop.
-------------------------------------------------------------
Testing for... 11.19 sec.
Testing foreach... 6.02 sec.
Difference: 46.17 %
-------------------------------------------------------------
Checks the difference between inline code, and function call.
1,000 times in loop.
-------------------------------------------------------------
Testing inline code... 9.03 sec.
Testing function call... 12.67 sec.
Difference: 28.73 %

 

<?php
// Checks the difference between the different functions / ways to do it in PHP

// Checks the difference between single quote and double quote
function quote_tests()
{
   $nb=50000000;
   echo "-------------------------------------------------------------\n";
   echo "Checks the difference between single quote and double quote.\n";
   echo number_format($nb)." times in loop.\n";
   echo "-------------------------------------------------------------\n";    

   echo "Testing single quote...";
   flush();
   $start=microtime(true);
   $t='';
   for($i=0;$i < $nb;$i++)
   {
       $t.=' a';
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_a=($end-$start);

   echo "Testing double quote...";
   flush();
   $start=microtime(true);
   $t="";
   for($i=0;$i < $nb;$i++)
   {
       $t.=" a";
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_b=($end-$start);
   echo "Difference: ".round(abs($res_a-$res_b)/max($res_a,$res_b)*100,2)." %\n";
}

// Checks the difference between echo and print
function output_tests()
{
   $nb=10000000;
   echo "-------------------------------------------------------------\n";
   echo "Checks the difference between echo and print.\n";
   echo number_format($nb)." times in loop.\n";
   echo "-------------------------------------------------------------\n";    

   echo "Testing echo function...";
   ob_start();
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       echo "Hi $i\n";
   }
   $end=microtime(true);
   ob_end_clean();

   echo " ".round($end-$start,2)." sec.\n";
   $res_a=($end-$start);

   echo "Testing print function...";
   ob_start();
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       print "Hi $i\n";
   }
   $end=microtime(true);
   ob_end_clean();

   echo " ".round($end-$start,2)." sec.\n";
   $res_b=($end-$start);
   echo "Difference: ".round(abs($res_a-$res_b)/max($res_a,$res_b)*100,2)." %\n";
}

// Checks the difference between concatenation and sprintf
function printf_tests()
{
   $nb=10000000;
   echo "-------------------------------------------------------------\n";
   echo "Checks the difference between concatenation and sprintf.\n";
   echo number_format($nb)." times in loop.\n";
   echo "-------------------------------------------------------------\n";    

   echo "Testing concatenation...";
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       $t="this string ".$i." plus another ".time()." to max ".$nb;
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_a=($end-$start);

   echo "Testing sprintf...";
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       $t=sprintf("this string %d plus another %d to max %d ",$i,time(),$nb);
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_b=($end-$start);
   echo "Difference: ".round(abs($res_a-$res_b)/max($res_a,$res_b)*100,2)." %\n";
}

define('NbWorldItems',100);

function DoInline($step)
{
   $world=array();
   srand(7000);
   // Fill the world with random coordinates (x, y, distance to nearest)
   for($i=0;$i < NbWorldItems;$i++)
       $world[]=array(rand(0,NbWorldItems),rand(0,NbWorldItems),0);

   // Now calculate the distance of each item to the nearest nearbor
   for($i=0;$i < NbWorldItems;$i++)
   {
       $isFirst=true;
       for($j=0;$j < NbWorldItems;$j++)
       {
           if($i == $j) // Skip ourself.
               continue;
           // Calculate the distance between the 2
           $x=$world[$i][0]-$world[$j][0];
           $y=$world[$i][1]-$world[$j][1];
           $d=sqrt($x*$x+$y*$y);
           if($isFirst || $d < $world[$i][2])            
               $world[$i][2]=$d;
           $isFirst=false;
       }
   }

   $small=0;
   for($i=1;$i < NbWorldItems;$i++)
   {
       if($world[$small][2] > $world[$i][2])
           $small=$i;
   }
   return $small;
}

function CalcDist($a,$b)
{
   $x=$a[0]-$b[0];
   $y=$a[1]-$b[1];
   return sqrt($x*$x+$y*$y);
}

function DoProcedural($step)
{
   $world=array();
   srand(7000);
   // Fill the world with random coordinates (x, y, distance to nearest)
   for($i=0;$i < NbWorldItems;$i++)
       $world[]=array(rand(0,NbWorldItems),rand(0,NbWorldItems),0);

   // Now calculate the distance of each item to the nearest nearbor
   for($i=0;$i < NbWorldItems;$i++)
   {
       $isFirst=true;
       for($j=0;$j < NbWorldItems;$j++)
       {
           if($i == $j) // Skip ourself.
               continue;
           // Calculate the distance between the 2
           $d=CalcDist($world[$i],$world[$j]);
           if($isFirst || $d < $world[$i][2])            
               $world[$i][2]=$d;
           $isFirst=false;
       }
   }

   $small=0;
   for($i=1;$i < NbWorldItems;$i++)
   {
       if($world[$small][2] > $world[$i][2])
           $small=$i;
   }
   return $small;
}

class WorldItem
{
   public $x,$y,$d;

   public function WorldItem()
   {    
       $this->x=rand(0,NbWorldItems);
       $this->y=rand(0,NbWorldItems);
       $this->d=0;
   }

   public function Distance($item_b)
   {
       $a=$this->x-$item_b->x;
       $b=$this->y-$item_b->y;
       return sqrt($a*$a+$b*$b);
   }

   public function MinDistance($world)
   {        
       $isFirst=true;
       foreach($world as $w)
       {
           if($w == $this)
               continue;
           $t=$this->Distance($w);
           if($isFirst || $t < $this->d)
               $this->d=$t;
           $isFirst=false;
       }
   }
}

function DoOO()
{
   srand(7000);
   $world=array();
   // Fill the world with random coordinates (x, y, distance to nearest)
   for($i=0;$i < NbWorldItems;$i++)
       $world[]=new WorldItem();

   // Now calculate the distance of each item to the nearest nearbor
   for($i=0;$i < NbWorldItems;$i++)
       $world[$i]->MinDistance($world);

   $small=0;
   for($i=1;$i < NbWorldItems;$i++)
   {
       if($world[$small]->d > $world[$i]->d)
           $small=$i;
   }
   return $small;        
}

function oo_tests()
{
   $nb=1000;
   echo "-------------------------------------------------------------\n";
   echo "Checks the difference between procedural and OO.\n";
   echo number_format($nb)." times in loop.\n";
   echo "-------------------------------------------------------------\n";    

   echo "Testing procedural...";
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       $t=DoProcedural($i);
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_a=($end-$start);

   echo "Testing OO...";
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       $t=DoOO($i);
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_b=($end-$start);
   echo "Difference: ".round(abs($res_a-$res_b)/max($res_a,$res_b)*100,2)." %\n";
}

// Checks the difference between for and foreach
function loop_tests()
{
   $nb=100000;
   $nbElements=1000;

   echo "-------------------------------------------------------------\n";
   echo "Checks the difference between for and foreach.\n";
   echo number_format($nb)." times for ".number_format($nbElements)." in loop.\n";
   echo "-------------------------------------------------------------\n";    

   $data=array();
   srand(10000);
   for($i=0;$i < $nbElements;$i++)
       $data[]=rand(0,100);

   echo "Testing for...";
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       $sum=0;
       for($j=0;$j < $nbElements;$j++)
           $sum+=$data[$j];
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_a=($end-$start);

   echo "Testing foreach...";
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       $sum=0;
       foreach($data as $j)
           $sum+=$j;
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_b=($end-$start);
   echo "Difference: ".round(abs($res_a-$res_b)/max($res_a,$res_b)*100,2)." %\n";
}

// Checks the difference between inline code, and function call.
function inline_tests()
{
   $nb=1000;
   echo "-------------------------------------------------------------\n";
   echo "Checks the difference between inline code, and function call.\n";
   echo number_format($nb)." times in loop.\n";
   echo "-------------------------------------------------------------\n";    

   echo "Testing inline code...";
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       $t=DoInline($i);
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_a=($end-$start);

   echo "Testing function call...";
   flush();
   $start=microtime(true);
   for($i=0;$i < $nb;$i++)
   {
       $t=DoProcedural($i);
   }
   $end=microtime(true);

   echo " ".round($end-$start,2)." sec.\n";
   $res_b=($end-$start);
   echo "Difference: ".round(abs($res_a-$res_b)/max($res_a,$res_b)*100,2)." %\n";
}

$tests=array("quote_tests","output_tests","printf_tests","oo_tests","loop_tests","inline_tests");
foreach($tests as $t)
   $t();
  • Like 1
Link to comment
Share on other sites

Thanks for shedding some light on this, I always wondered what the differences were myself but never really understood all of things like for and foreach. Is there a time to use for over foreach or vice versa? And I never really understand how to use sprintf and where people get %d or %s or whatever have you

Link to comment
Share on other sites

for is useful if you need a variable which is a number inside the loop, like, I want one dot every 10 step or so:

for($i=0;$i < 1000;$i+=10)

foreach is to go through all elements of an array while having the reference of the current element. So if you don't "browse" an array, foreach is not for you.

sprintf is the descendent of the equivalent function in C. You can use sprintf, printf, and fprintf they all work the same way. %d, %f and any % something are place holders which will be filled with the data taken after the first argument. I will not explain all the options here, but you can use %s for a string, %d for an integer, %f for a floating point.

Link to comment
Share on other sites

I'm sorry, but I still find this post completely unnecessary and potentially harmful to new coders.

Is the average fresh fish going to know that the likelihood of having 100,000+ for calls that loop over 1,000 times is extremely low? Probably not.

Again, I just feel like, many newer coders will take this advice the wrong way. Not to mention, you just know someone's going to debate the results.

I say, this post is more trouble than it's worth.

Link to comment
Share on other sites

Very handy post, I remember there being many posts around here about which methods are better/quicker to do with coding and you've just nailed it on the head.

Don't suppose you could do a nice benchmark test on the differences between

++$i;
$i++

As this came up a few years ago.

Link to comment
Share on other sites

Very handy post, I remember there being many posts around here about which methods are better/quicker to do with coding and you've just nailed it on the head.

Don't suppose you could do a nice benchmark test on the differences between

 

++$i;
$i++

 

As this came up a few years ago.

http://stackoverflow.com/questions/1756015/whats-the-difference-between-i-and-i-in-php

 

++$i is pre-increment whilst $i++ post-increment.

pre-increment: increment variable i first and then de-reference.

post-increment: de-reference and then increment i

 

"Take advantage of the fact that PHP allows you to post-increment ($i++) and pre-increment (++$i). The meaning is the same as long as you are not writing anything like $j = $i++, however pre-incrementing is almost 10% faster, which means that you should switch from post- to pre-incrementing when you have the opportunity, especially in tight loops and especially if you're pedantic about micro-optimisations!" -

Link to comment
Share on other sites

Spudinski: the code is there, try to find how I made a mistake. I have a good explanation for the sprintf and quiet a good one for foreach too, even if those two surprised me as well. BTW I ran the code multiple times to check it.

For sprintf, the trick is that it goes directly to the C code function, and therefore there is basically no interpretation, where the concatenation need to interpret every "couple" as orations like that are binary (2 operands) operators. Therefore the concatenation is slower due to more interpretation vs a single C code. That's how I can explain it.

For the foreach, I was sure it was slower than the for, yet I found this... disturbing result. How can I explain it? Well, simply because the foreach don't need to do a check and an increment on the interpreter level and all is handled on the lower level. I cannot explain it otherwise. Result found by somebody else:

http://www.phpbench.com/ "Read Loop:foreach() vs. for() vs. while(list() = each()) " => foreach is faster.

BTW I don't count the time with loops spudinski, I count the time the operation took, and as those things are fast I added a loop around to take time. I hardly see how I could have made it wrong, but if you find bugs or wrong results, please share your findings!

Seker: any pure benchmark is not all that useful by itself, and indeed you will very rarely (if ever) do the same kind of operations as the code I gave here. Also I believe my statements are quiet clear: better keep your code readable instead of trying to grab some speed. However I do believe that benchmarks show that some stuff that many (me included) didn't know, like speed differences of the for / foreach and maybe the cost of OO programming (again PREFER READABLE CODE over clumsy one just to be faster).

Link to comment
Share on other sites

I'm sorry, but I still find this post completely unnecessary and potentially harmful to new coders.

Is the average fresh fish going to know that the likelihood of having 100,000+ for calls that loop over 1,000 times is extremely low? Probably not.

Again, I just feel like, many newer coders will take this advice the wrong way. Not to mention, you just know someone's going to debate the results.

I say, this post is more trouble than it's worth.

How is it harmful to new coders? If anything its telling them not to panic after reading a post saying your code will be faster if you do it like this so they rush off change pages of code and then discover that actually they have saved 0.0006 ms wahoo!!!

If anything its really telling coders to do your research if you wish to know the difference between print and echo, for and foreach , keep your code clean and keep learning that is all.

Link to comment
Share on other sites

Ran the code on a Linux Scientific Linux 5.1 (Cent OS 5.1 equivalent):

PHP: 5.1.6

 

-------------------------------------------------------------
Checks the difference between single quote and double quote.
50,000,000 times in loop.
-------------------------------------------------------------
Testing single quote... 7.12 sec.
Testing double quote... 7.27 sec.
Difference: 2.08 %
-------------------------------------------------------------
Checks the difference between echo and print.
10,000,000 times in loop.
-------------------------------------------------------------
Testing echo function... 7.84 sec.
Testing print function... 7.89 sec.
Difference: 0.66 %
-------------------------------------------------------------
Checks the difference between concatenation and sprintf.
10,000,000 times in loop.
-------------------------------------------------------------
Testing concatenation... 18.07 sec.
Testing sprintf... 16.6 sec.
Difference: 8.12 %
-------------------------------------------------------------
Checks the difference between procedural and OO.
1,000 times in loop.
-------------------------------------------------------------
Testing procedural... 18.01 sec.
Testing OO... 21.23 sec.
Difference: 15.13 %
-------------------------------------------------------------
Checks the difference between for and foreach.
100,000 times for 1,000 in loop.
-------------------------------------------------------------
Testing for... 12.26 sec.
Testing foreach... 8.9 sec.
Difference: 27.4 %
-------------------------------------------------------------
Checks the difference between inline code, and function call.
1,000 times in loop.
-------------------------------------------------------------
Testing inline code... 11.62 sec.
Testing function call... 18.18 sec.
Difference: 36.09 %

 

Results are basically the same beside we see about 2% of difference between single and double quote... not something which would lead me to change even a single line of my code.

Link to comment
Share on other sites

Thought I'd run the rest quickly as well, just for those that are interested. Running on a ubuntu11.04 desktop, with php5.3.5

 

-------------------------------------------------------------
Checks the difference between single quote and double quote.
50,000,000 times in loop.
-------------------------------------------------------------
Testing single quote... 7.13 sec.
Testing double quote... 7 sec.
Difference: 1.82 %
-------------------------------------------------------------
Checks the difference between echo and print.
10,000,000 times in loop.
-------------------------------------------------------------
Testing echo function... 5.45 sec.
Testing print function... 5.65 sec.
Difference: 3.46 %
-------------------------------------------------------------
Checks the difference between concatenation and sprintf.
10,000,000 times in loop.
-------------------------------------------------------------
Testing concatenation... 17.29 sec.
Testing sprintf... 16.38 sec.
Difference: 5.26 %
-------------------------------------------------------------
Checks the difference between procedural and OO.
1,000 times in loop.
-------------------------------------------------------------
Testing procedural... 15.03 sec.
Testing OO... 21.04 sec.
Difference: 28.56 %
-------------------------------------------------------------
Checks the difference between for and foreach.
100,000 times for 1,000 in loop.
-------------------------------------------------------------
Testing for... 12.18 sec.
Testing foreach... 9.06 sec.
Difference: 25.63 %
-------------------------------------------------------------
Checks the difference between inline code, and function call.
1,000 times in loop.
-------------------------------------------------------------
Testing inline code... 11.63 sec.
Testing function call... 15.16 sec.
Difference: 23.3 %

 

I've also ran the test on a real server with php 5.3.10, results below

-------------------------------------------------------------
Checks the difference between single quote and double quote.
50,000,000 times in loop.
-------------------------------------------------------------
Testing single quote... 5.61 sec.
Testing double quote... 5.64 sec.
Difference: 0.6 %
-------------------------------------------------------------
Checks the difference between echo and print.
10,000,000 times in loop.
-------------------------------------------------------------
Testing echo function... 4.13 sec.
Testing print function... 4.79 sec.
Difference: 13.9 %
-------------------------------------------------------------
Checks the difference between concatenation and sprintf.
10,000,000 times in loop.
-------------------------------------------------------------
Testing concatenation... 11.77 sec.
Testing sprintf... 10.91 sec.
Difference: 7.29 %
-------------------------------------------------------------
Checks the difference between procedural and OO.
1,000 times in loop.
-------------------------------------------------------------
Testing procedural... 15.67 sec.
Testing OO... 17.22 sec.
Difference: 9.01 %
-------------------------------------------------------------
Checks the difference between for and foreach.
100,000 times for 1,000 in loop.
-------------------------------------------------------------
Testing for... 12.14 sec.
Testing foreach... 8.88 sec.
Difference: 26.84 %
-------------------------------------------------------------
Checks the difference between inline code, and function call.
1,000 times in loop.
-------------------------------------------------------------
Testing inline code... 11.56 sec.
Testing function call... 15.69 sec.
Difference: 26.33 %

Link to comment
Share on other sites

Any chance next discussion (sorry... thread) being about angels gender?

 

Very handy post, I remember there being many posts around here about which methods are better/quicker to do with coding and you've just nailed it on the head.

Don't suppose you could do a nice benchmark test on the differences between

 

++$i;
$i++

 

As this came up a few years ago.

I believe i started this in the middle of some rant, and i am sure i told back then pre-incrementing was faster! ;)

Edited by Lithium
Link to comment
Share on other sites

  • 3 weeks later...
God dammit, people should stop bitching about this.

Hold on a second, didn't you not so long ago get on my case for stating pretty much the exact same thing?

Something along lines of;

My link was at the print vs echo, not at the quotes.

As for what I said, wasn't mean't to be taken as 'you are not allowed an opinion', it was meerly stating that the speed difference is so little the fact that your using " single is faster than double so use single " is silly.

Like I said last time, use whichever you find easiest, but don't worry about the speed difference, as 99.8% you won't see a negative or a positive effect from using one or the other.

Also on that note there is no right or wrong way.

---Spud:---

Also, debating it isn't silly(sorry Djk) - high performance optimizations is one of the key parts in programming.

If there's a faster/better/more efficient way of doing something, I'm sure as hell going to find it AND point it out.

Edited by Djkanna
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...