6

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

9
  • 2
    Can you give us a print_r($values);die;? Commented Dec 16, 2009 at 15:08
  • I did a var_dump($values), but since one property of a 'Value' object is another object which in turn has an array of other objects, the dump gets much longer than my 10'000 lines of Command Line Buffer. Commented Dec 16, 2009 at 15:15
  • In other words, 'Value' objects aren't small objects, but are actually the tops of large object graphs? Commented Dec 16, 2009 at 15:36
  • They are small in that they only have one float and one object as properties. But yes, the object graphs grow large, with a lot of cross reference and even circular references further down. Commented Dec 16, 2009 at 15:44
  • $val = &$values[...]; <-- This syntax is wrong, it should be $val =& $values[...]; Commented Dec 16, 2009 at 15:50

2 Answers 2

3

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?

Sign up to request clarification or add additional context in comments.

2 Comments

No, I'm not familiar with xdebug or the Zend Debugger. Checking out the Spl data structures...
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.
1

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

2 Comments

Objects in PHP are always assigned by reference. This would be excellent advice if each $val weren't an object, though.
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)...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.