views:

249

answers:

2

I'm seeing a huge performance decline in a (command line) PHP script, caused by a simple assignment (runtime increase from 0.8 ~ 0.9 seconds to 29.x seconds).

The script first fetches a lot of data from a MySQL database and creates objects of different custom classes. After this fetching (php now uses around 500 MB of RAM) I loop an array of approximately 3'500 Sample objects, each of which has an associative array (size around 100 entries) as one of its properties. This array holds Value objects, which are small objects with two properties, and the keys are integers smaller than 6'000. This is where I stumbled upon the problem, see this code:

foreach ($samples as $id => $s) {    # $s is now a 'Sample' object
    $values = $s->values();          # $values is an array of 'Value' objects

    if (isset($values[$match_id])) {
        $num_tested++;
        # $val = $values[$match_id];     # contains a 'Value' object
        # $val = &$values[...]; -> the loop never ends (!)
    }
}

Note that commented line. If I run the code as it appears here, this block runs for about 0.8 to 0.9 seconds. If I uncomment this single line, the block runs for almost 30 seconds. I found that if the array is non-associative (it only contains consecutive keys from 0 to about 100) the runtime only increases to 1.8 ~ 1.9 seconds.
It seems that this happens because of the non-consecutive array keys I use, but then again why does the performance not already decline by calling isset($values[$match_id])? Is there a workaround for this or do I have to live with that?

Running PHP 5.3.0, Zend Engine v2.3.0, Mac OS X Server 10.6.2

+3  A: 

If you are running 5.3, look into the new Spl data structures. They can yield a significant performance boost for larger collections, as shown here and here. Apart from that, it's a bit hard to tell what might be causing the issue. Have you tried to use xdebug or Zend_Debugger to get more details?

Gordon
No, I'm not familiar with `xdebug` or the Zend Debugger. Checking out the Spl data structures...
Pascal
xdebug and Zend_Debugger allow you to profile your application. They can give you a detailed analysis of what methods are called, how often and how long they take to run. xdebug is free, so why not have a look at it.
Gordon
+1  A: 

Try replacing $val = $values[$match_id] (assignment by copy) with $val =& $values[$match_id] (assignment by reference) and see if it performs better.

Lukman
Objects in PHP are always assigned by reference. This would be excellent advice if each $val weren't an object, though.
Lucas Oman
I haven't tried that since - as Lucas mentions - objects are always assigned by ref. Interesting thing about this is: **The loop does not come to an end** (at least it did not after 10 minutes, when I killed it)...
Pascal