• PHP Performance Tip - reducing use of strlen()
    11/09/2010 6:24PM

    Ok, if I hadn't just used xdebug and kcachegrind to analyze why a page of bookmarks was rendering so slowly I would not have believed what I've discovered.

    Because of the way I do my own variable expansion and expression parsing for FVML, I do a lot of string parsing in PHP, which is, of course, notoriously slow. To make things more complicated, I also support inline functions which can be included in strings such as; $$if(<condition>,if true,if false).

    One particular page in the code I'm writing for both Miles-By-Motorcycle.com and appupdate.com was running ridiculously slowly. Using formVista's own performance profiling tools that I had built wasn't really giving me the insights I needed. I could tell the bottleneck was in the render phase of the main loop of a list, but I couldn't tell

    I had installed the XDebug PHP profiler some time ago. It outputs "cachegrind" files in /tmp which can then be analyzed visually with KCachegrind.

    After looking at several runs, to my shock and horror over 18% of the execution time was spend in a method called fv_baseCtrl::procFunctionParms(). It doesn't really do much. It just loops through a string fragment and counts up parentheses, quotes and the like to break apart of the parameter list while taking into account nested functions and variable lists. There's nothing to it.

    After trying some optimizations by reducing the number of arrays I was using and removing a few unnecessary lines of code I wasn't seeing a clear way of further optimizing the code.

    I did some googling around and came across a list of performance improvement suggestions over at atomized.org. (NOTE: the article is old and some optimizations described do not apply to PHP 5). One thing that caught my eye was the suggestion not to use built-in functions in loop constructs such as:

    while ( $offset < strlen($somestring) )
       {
       // do something
       $offset++;
       }

    which is exactly what I was doing when looping over the characters in the string. To see if it would make any improvement at all I moved the strlen() call out of the loop as in:

    $string_length = strlen( $somestring );
    while ( $offset < $string_length)
       {
       // do something
       $offset++;
       }

    Just this simple change yielded a 72% speed improvement in the loop. I had assumed PHP caches the length of a string along with the string object and flags it as dirty, i.e. in need of recalculating, when the string changes, which is how I would have built the language, but it looks like, based on these numbers, that PHP must literally be looping over the entire string each time to calculate it's length even when the string has not changed since the last time strlen() was used.

    Interesting. I would never have assumed that this would make such a huge performance difference.

    Live and learn.

    While on the topic of performance tuning I came across another article:

    http://kevin.vanzonneveld.net/techblog/article/survive_heavy_traffic_with_your_webserver