Breadcrumbs

Micro-optimisations in PHP

I'm nearing the time when I need to start benchmarking the code of a project I'm working on and I have been browsing around the web for some various tips on optimising PHP code. So far I've come across a few fairly authoritative-looking lists with up to 63 different tips for optimising PHP code (one of which is the original list with a number of new tips added). The best formatted list is at PHP Bench (external link); however, it's a fairly limited sample. The lists at Reinhold Weber's website (external link) and Chazzucka (external link) contain significantly more tips, but don't provide much in the way of figures.

As an example, one of the tips says that using the parameterised version of echo (external link) is faster than using concatenation. Indeed it is. In my own test, I found that the parameterised version of the echo statement was roughly 5% faster than using string concatenation. There is one thing that still needs to be taken into account though. I ran the statement 5000 times using a large, heavily concatenated/parameterised string. For most any site, having 5000 echo statements is a giant sign that the site has been poorly constructed and needs more than a quick optimisation.

With over 5000 echo statements, the parameterised version saved me a total of 0.2 seconds. So on a site with a reasonable 50 echo statements, that would save you 0.002 seconds, hardly noticeable to the end user.

Another tip says that calculating values before entering a loop significantly speeds up the performance of an algorithm.

Take these two loops, where the only difference is the initialisation statement. Loop One first calls count() and stores its return value in a variable and uses that variable in its initialisation statement. Loop Two uses the count() function directly. Both count() functions will be passed an array with 100 elements.

Code: PHP

<?php
$limit 
count($array);
for (
$ii 0$ii $limit$ii++)
{
    
// do nothing
}
?>

Code: PHP

<?php
for ($ii 0$ii count($array); $ii++)
{
    
// do nothing
}
?>

Like the echo test, both of these functions were ran 5000 times over 10 tests and the averages were recorded. Loop One produced a total time of 1.0231914520276 seconds, while Loop Two produced a total time of 3.830361366272 seconds. This is a difference of 27%, which is a very significant performance boost.

The one thing to take from this is that some optimisations will be more worthwhile than others. Even though any improvement is a good improvement, it's best to focus your efforts on the tips that provide the greatest improvements. For most sites, an extra 0.002 seconds of processing time isn't going to make or break anything; but saving an extra 27% here or there can yield noticeable improvements.

Comments

  • I've recently read 2 good articles about choosing which optimisations to make in your code:

    -http://www.codinghorror.com/blog/archives/001223.html (external link)

    -http://www.codinghorror.com/blog/archives/001218.html (external link)

    Those article are witten by the guy behind Stack Overflow. Really interesting blog if you're interested.

    Posted by Matt Oakes (external link) on Thu 12 Feb 2009 at 1:50

  • In my opinion, these kinds of micro-optimisations should be performed while you are writing the code since they do not obfuscate the code (or, as Sutter and Alexandrescu put it in "C++ Coding Standards", "don't pessimize prematurely"). If you have not done them, generally you should not bother picking around to change the code, unless you are really facing a performance problem and the more macro scale optimisations have already been made.

    Speaking of more macro scale optimisations, I think that things like tweaking database indices could potentially result in much better performance, in addition to the usual "use a better algorithm" kind of optimisations.

    Incidentally, there is another advantage to moving the call to count() to either before the loop, or in the initialisation statement: it more clearly identifies the operation as invariant to the loop.

    Posted by Eugene Wee on Thu 12 Feb 2009 at 12:12

  • I agree with Eugune that these types of optimisations are best to do during programming because it isn't worth the time and effort to do so afterwards. I don't think that most of these optimisations would be a huge saver, but it isn't bad practice to start using them in any future projects.

    Posted by Ethan Poole (external link) on Thu 12 Feb 2009 at 14:31

  • I'm going to have to agree and disagree with the two of you.

    I'll agree that optimizing the code while you're writing it is smart, and optimizing possible bottlenecks like the database is as well.

    But to say 'forget about it' just because it's been written and its 'good enough' is something I really can't agree with.

    If a program has been completed I really don't see any harm is targeting an area of it (a hotspot for instance) and doing everything you can to optimize it; apart from what I mentioned about the 'echo' optimization which is nearly useless. Pick the optimizations that work and use them.

    This is what the FreeBSD developers did with the TCP stack and imporved performance by a factor of 3-5 times.http://www.onlamp.com/pub/a/bsd/2008/02/26/whats-new-in-freebsd-70.html (external link)

    Yeah they weren't 'really facing a performance problem' before, but they made it better, so what's the problem with that?

    Posted by -=Hero Doug=- on Thu 12 Feb 2009 at 21:06

  • If you already have a complex application, it usually isn't cost effecient to go back through and change everything. You'd have to go through with a fine comb for all these micro optimisations, which takes a lot of time. Granted, if you have the time it wouldn't hurt, but most developers are pretty busy.

    Posted by Ethan Poole (external link) on Thu 12 Feb 2009 at 22:49

  • Wow, that's quite the difference. I hadn't expected it to be that large.

    Posted by Frans (external link) on Fri 13 Feb 2009 at 7:21

  • This is what the FreeBSD developers did with the TCP stack and imporved performance by a factor of 3-5 times.

    Let us see what the developers say they did: "careful analysis and lots of code profiling".

    In other words, they did not just pick out some part of the code and apply micro-optimisations. Rather, they profiled the code to find bottle necks, then applied macro-optimisations to those portions, possibly also applying micro-optimisations while they were at it.

    Yeah they weren't 'really facing a performance problem' before, but they made it better, so what's the problem with that?

    If they were motivated enough to optimise as they did, then they had a performance problem. It might not be a performance problem that was apparent to users, but somewhere along the line they reviewed and possibly revised their performance goals and decided that the optimisation was necessary.

    Posted by Eugene Wee on Fri 13 Feb 2009 at 9:47

  • Man, I hate arguing over a topic on which we essentially agree.

    Quotation by "Ethan"

    If you already have a complex application, it usually isn't cost effecient to go back through and change everything.

    Quotation by "Eugene"

    Let us see what the developers say they did: "careful analysis and lots of code profiling".

    In other words, they did not just pick out some part of the code and apply micro-optimisations. Rather, they profiled the code to find bottle necks, then applied macro-optimisations to those portions, possibly also applying micro-optimisations while they were at it.

    Quotation by "Douglas"

    If a program has been completed I really don't see any harm in targeting an area of it (a hotspot for instance) and doing everything you can to optimize it;

    As you can see, I didn't suggest changing "everything", or picking some "random" portion of code to optimize. I said "target an area", and I even provided an example of which area would be good to begin with, a hot spot.

    Quotation by "Eugene"

    ... then applied macro-optimisations to those portions, possibly also applying micro-optimisations while they were at it.

    Maybe since this discussion took place within the context of the blog post you assumed that when I said "doing [b]everything[/b] you can to optimize it" you thought I was only talking about using the kind of optimizations I posted about; but that was not my meaning at all sir, which is why I said "everything".

    Quotation by "Eugene"

    If they were motivated enough to optimise as they did, then they had a performance problem. It might not be a performance problem that was apparent to users, but somewhere along the line they reviewed and possibly revised their performance goals and decided that the optimisation was necessary.

    This last quote is a very semantic discussion, no use in getting into that wink

    Posted by -=Hero Doug=- on Fri 13 Feb 2009 at 23:22