【问题标题】:PHP array performancePHP数组性能
【发布时间】:2011-06-21 16:50:58
【问题描述】:

我正在测试一种用于 2d bin 打包的算法,我选择 PHP 来模拟它,因为它是我现在的基本语言。

正如您在http://themworks.com/pack_v0.2/oopack.php?ol=1 上看到的那样,它运行良好,但您需要等待大约 10-20 秒才能打包 100 个矩形。对于一些难以处理的集合,它会达到 php 的 30 秒运行时限制。

我做了一些分析,它表明大多数时候我的脚本会遍历一个包含 0 和 1 的小型二维数组的不同部分。它要么检查某个单元格是否等于 0/1,要么将其设置为 0/1。它可以进行数百万次这样的操作,每次只需要几微秒。

我想我可以在静态类型语言中使用一组布尔值,这样会更快。或者甚至制作一个 1 位值的数组。我正在考虑将整个事情转换为某种编译语言。 PHP 是不是不适合它?

如果我确实需要将其转换为 C++,那么自动转换器有多好?我的脚本只是很多带有基本数组和对象操作的 for 循环。

编辑。这个函数被调用的次数比其他任何函数都多。它读取一个非常简单的对象的几个属性,并通过一个很小的数组的一小部分来检查是否有任何不等于 0 的元素。

function fits($bin, $w, $h, $x, $y) {

    $w += $x;
    $h += $y;

    for ($i = $x; $i < $w; $i++) {

        for ($j = $y; $j < $h; $j++) {

            if ($bin[$i][$j] !== 0) {
                return false;
            }
        }
    }

    return true;    
}

更新:我尝试使用 1d 数组而不是 2d 作为建议的答案之一。由于我需要始终访问当前的 bin 宽度,因此我决定将所有内容包装在对象中。此外,现在在每个循环中都需要计算索引。现在脚本需要更多时间来运行。其他技术并没有带来太多的性能提升,而是降低了代码的可读性。我猜 HipHop 的时间到了。

更新:由于 hiphop php 只在 linux 上运行,而我没有,我决定用 C++ 重写整个东西。更新旧技能很好。另外,如果我确实找到了一种使用 hiphop 的方法,比较手写的 C++ 代码和 hiphop 生成的代码会很有趣。

更新:我用 c++ 重写了这个东西,平均它的工作速度快了 20 倍并且使用的内存少得多。让我看看我能不能让它更快。

【问题讨论】:

  • 您的代码编写效率可能非常低,但除非我们看到它,否则我们无法知道这一点。虽然 PHP 通常比编译语言慢,但这并不意味着是语言的缓慢导致代码执行时间过长
  • 不要在 PHP 中编写任何对性能敏感的东西。最好的办法是用 C++ 编写(试试 hip-hop)。
  • 嘿 dfo,如果可能的话,我们能看到一些代码来处理一直占用的部分吗?也许有人可以建议对算法进行一些改进或更好地存储您的数据。
  • php.net/manual/en/function.set-time-limit.php 重置 30 秒时间限制运行时间。您可能还想使用二进制字符串或整数和按位运算符,而不是使用 1 和 0 的数组。
  • 如果你将它转换成 c++ 粘贴这里的时间比较

标签: php arrays performance


【解决方案1】:

PHP 中的数组访问肯定会很慢。 PHP 使用哈希表来实现数组,即为了访问数组中的元素,它必须计算哈希并遍历链表。使用带有真实数组的编译语言肯定会提高性能,因为可以直接访问内存。感兴趣的朋友:hash access with stringwith integer 的代码。

关于你的代码,有几点我会优化:

  • 直接return,不要break两次。
  • $file-&gt;get_width()$file-&gt;get_height 放入简单的变量中。我假设高度或宽度在整个过程中都不会改变。请记住:PHP 中的函数很慢。
  • 使用一维数组,而不是嵌套数组。以这种方式,每次迭代都可以保存一个哈希查找。 实际上,一维数组只是稍微快一点,甚至稍微慢一点。 Comparison of several ways of saving the data concerning performance and memory usage

.

function fits($bin, $x, $y, $w, $h) {
    $w += $x;
    $h += $y;

    for ($i = $x; $i < $w; ++$i) {
        for ($j = $y; $j < $h; ++$j) {
            if ($bin[$i][$j] !== 0) {
                return false;
            }
        } 
    }

    return true;   
}

虽然我不确定,但为什么要将 $x 添加到 $width / $y$height。您不想从当前坐标迭代到图像边界吗?

【讨论】:

  • 与往常一样,我希望能对否决票作出解释。
  • @nikic:我自己并没有对你投反对票。但是 PHP 不仅通过哈希关联地访问数组,它还具有顺序访问。
  • @Orbling:我检查了 lxr,发现对于连续的数字数组,仍然使用哈希表。显然,如果索引是数字的,则有几种简化,例如不需要计算哈希,而只需应用表掩码。当遍历链表时,检查显然要简单得多,因为比较的是数字而不是字符串。但基本上它的功能是相同的。它仍然是哈希表查找,有一些优化,但仍然是哈希表查找。它不像 C 语言那样直接访问内存。
  • @dfo - 基于 nikic 的修改,这个建议属于微优化的范畴……但有时(尤其是在使用紧密循环时)微优化可以产生明显的不同。您可能会发现 while 循环比 for 循环更快: $i = $x-1;而 (++$i
  • PHP7 修复了阵列性能。如果您使用 PHP 7 打包数组(键必须是整数并且以升序出现的数组),性能可以提高 10 倍。压缩数组的行为类似于真正的数组,而不是慢速哈希表。
【解决方案2】:

您的问题的解决方案可能是https://github.com/facebook/hiphop-php/wiki/

正如其他人所说,PHP 不是计算密集型任务的最佳语言。它也没有真正的数组类型。 PHP 中描述为array() 的内容实际上是一个字典/哈希映射。它有一些优化可以兼作列表,但正如您已经发现的那样,它没有提供与 C 指针和数组相同的运行时行为。

HipHop 可以将 PHP 代码转换为优化的 C++。它也针对字符串操作,但它可以很好地提供适当的数组/列表转换。

免责声明:我从未尝试过。只是想在这里提供一个听起来很聪明的答案。

【讨论】:

    【解决方案3】:

    截至 2018 年需要更新的答案。

    这个问题很老,在 PHP 7 中给出的答案并不完全正确如果你使用打包数组。因为这个问题首先出现在谷歌上,所以我添加了一个新答案

    如果您在 PHP 7 中仅使用整数作为数组键,并确保将它们按升序插入数组,您可以看到数组运算速度提高了 10 倍。

    在这里阅读: Blackfire Blog on PHP 7 Array Improvements

    【讨论】:

      【解决方案4】:

      建议另一种 PHP 替代方案:

      你看过SplFixedArray吗?

      根据您的数组的结构方式(线性 0 到 x)数组,这可以更快地执行

      有关基准,请参阅:http://www.slideshare.net/tobias382/new-spl-features-in-php-53 Slide 15 & 16(抱歉,没有找到更好的)

      【讨论】:

      • 我更新了我的测试以包含固定数组:gist.github.com/813289 对于多维缓存数组,它稍微快一些,对于平面数组它比较慢。它的好处是它使用的内存更少,因为它保存了所有与哈希表/桶相关的东西。
      • 它在多维数组中要慢得多,因为实际上由于对象创建开销 - 当数组开始包含很多东西时,这会消失。
      【解决方案5】:

      最近的替代方案是 PHP 的 QB 扩展,专门用于帮助解决此类问题。

      虽然 PHP 是构建复杂网络的优秀语言 应用,它施加了一定的限制。编写代码 在 PHP 中执行低级、计算密集型任务是 通常是不切实际的——它太慢了。 QB 扩展 解决了 PHP 的这个特殊弱点。通过翻译 Zend 操作码 并通过静态类型的虚拟机 QB 执行它们 提供数量级的性能增益。增加的力量 允许 PHP 程序员做他们以前不能做的事情,比如 复杂的像素级图像处理。

      见:http://php-qb.net/

      ^本网站不再包含PHP-QB项目(2022)

      【讨论】:

        【解决方案6】:

        PHP 中的数组确实看起来很慢,尤其是循环遍历多维数组。 另一种选择是尝试Quercus。它是用 Java 实现的 PHP。我想它使用Java数组。不过我没有做过比较。

        【讨论】:

          【解决方案7】:

          这个问题几乎可以说是“主要基于意见”。考虑到这一点:

          “PHP 不适合它吗?”

          PHP 最初只是一种 Web 模板语言,在设计时简单性比性能更受关注。它随着时间的推移而发展,并添加了许多优化,但是 PHP 的性能相对于其他平台来说相对较差。因此,如果您的标准是性能,那么 PHP 就不适合它。

          “我正在考虑将整个东西转换成某种编译语言。”

          从技术上讲,PHP 也可以编译。 Facebook 有一个 PHP to C++ 编译器。 Zend 有一种即时编译器。曾经有一个 PHP on Java 解释器(如果我没记错的话,虽然不再活跃了)。

          我建议您尝试 Java,因为它的语法相似,毕竟它是 PHP 5 的灵感之一。从 JDK 1.5 开始,Java 字节码被编译为本机代码。对于相同的代码结构,性能应该提高 4 倍(假设您使用社区 PHP 发行版)。

          【讨论】:

            猜你喜欢
            • 2013-05-12
            • 2011-02-15
            • 1970-01-01
            • 2013-06-11
            • 1970-01-01
            • 2011-12-25
            • 2013-07-05
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多