【问题标题】:Huge performance decline when accessing object in associative PHP array访问关联 PHP 数组中的对象时性能大幅下降
【发布时间】:2009-12-16 14:57:39
【问题描述】:

我发现(命令行)PHP 脚本的性能大幅下降,这是由一个简单的分配引起的(运行时间从 0.8 ~ 0.9 秒增加到 29.x 秒)。

脚本首先从 MySQL 数据库中获取大量数据并创建不同自定义类的对象。在此获取之后(php 现在使用大约 500 MB 的 RAM),我循环一个大约 3'500 个Sample 对象的数组,每个对象都有一个关联数组(大小约为 100 个条目)作为其属性之一。该数组保存Value对象,它们是具有两个属性的小对象,键是小于6'000的整数。这是我偶然发现问题的地方,请参阅以下代码:

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 (!)
    }
}

注意注释行。如果我运行此处显示的代码,此代码块将运行大约 0.8 到 0.9 秒。如果我取消注释这一行,该块将运行 几乎 30 秒。我发现如果数组是非关联的(它只包含从 0 到大约 100 的连续键),运行时间只会增加到 1.8 ~ 1.9 秒。
似乎这是因为我使用了不连续的数组键,但是为什么调用isset($values[$match_id]) 时性能还没有下降?有解决方法吗?还是我必须忍受?

运行 PHP 5.3.0、Zend Engine v2.3.0、Mac OS X Server 10.6.2

【问题讨论】:

  • 你能给我们一个print_r($values);die;吗?
  • 我做了一个var_dump($values),但由于“值”对象的一个​​属性是另一个对象,而该对象又具有一组其他对象,转储比我的 10'000 行长得多命令行缓冲区。
  • 也就是说,'Value'对象不是小对象,而是大对象图的顶端?
  • 它们很小,因为它们只有一个浮点数和一个对象作为属性。但是,是的,对象图变大了,有很多交叉引用,甚至是循环引用。
  • $val = &$values[...]; $val =& $values[...];

标签: php oop command-line


【解决方案1】:

如果您运行的是 5.3,请查看新的 Spl 数据结构。它们可以为更大的集合带来显着的性能提升,如herehere 所示。除此之外,很难说出可能导致问题的原因。您是否尝试过使用xdebugZend_Debugger 来获取更多详细信息?

【讨论】:

  • 不,我不熟悉 xdebug 或 Zend 调试器。检查 Spl 数据结构...
  • xdebug 和 Zend_Debugger 允许您分析您的应用程序。它们可以为您详细分析调用了哪些方法、它们运行的​​频率和运行时间。 xdebug 是免费的,何不来看看呢。
【解决方案2】:

尝试将$val = $values[$match_id](复制分配)替换为$val =& $values[$match_id](引用分配),看看效果是否更好。

【讨论】:

  • PHP 中的对象总是通过引用分配的。不过,如果每个 $val 都不是对象,这将是一个很好的建议。
  • 我没有尝试过,因为 - 正如卢卡斯提到的 - 对象总是由 ref 分配。有趣的是:循环没有结束(至少10分钟后没有结束,当我杀死它时)......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-21
  • 2022-01-07
  • 1970-01-01
  • 2014-08-22
  • 1970-01-01
  • 2014-01-16
  • 2018-11-12
相关资源
最近更新 更多