【问题标题】:Performance of array_merge vs union in PHPPHP中array_merge与联合的性能
【发布时间】:2018-06-30 23:33:22
【问题描述】:

出于好奇,我试图了解 array_mergeunion 如何在 PHP 的幕后工作。

有人可以帮我了解 ZEND 幕后的内部结构吗:

  • array_merge(在 CPU 和 RAM 上较慢)
  • UNION(各方面更快)

这是我正在运行的基准代码:https://gist.github.com/EnchanterIO/6e90f828c1b32c894d35267c353e83d2

使用 PHP 7 的输出是:

➜ ArrayMerge git:(master) ✗ php src/benchmark.php array_merge 20000

使用 array_merge 构建包含 20000 个元素的数组需要 7 秒。

内存使用量为:8 MB。内存峰值为:12288 MB。

➜ ArrayMerge git:(master) ✗ php src/benchmark.php union 20000

使用 union 构建包含 20000 个元素的数组耗时 0 秒。

内存使用量为:8 MB。内存峰值为:10240 MB。

我对 array_merge 的理论:

我正在查看PHP source code written in C for array merge(如果这甚至是正确的地方),尽管它对我来说有点难以理解,因为我不熟悉行话,这似乎是array_merge 速度较慢的原因是由于需要额外的 foreach 以及 array_merge 对结果数组中的数字键重新编号。

我对 UNION 的理论:

没有找到它的源代码,但据我所知,向数组添加元素的工作方式如下:

  • 一开始,数组内部分配了一些内存
  • 通过向数组添加新元素,最终数组需要在后台动态分配更多内存,因此 PHP 内部 (C) 会创建一个具有双倍内存量的新数组并复制内容
  • 通过添加更多元素重复此过程
  • 没有重新排序,没有 foreach,只是随着时间的推移增加内存

谁能更深入地了解这个过程并深入解释 ZEND 魔法的幕后故事?

更新:

我被提及以下链接,但仍然无法理解它:

https://lxr.room11.org/xref/php-src%40master/Zend/zend_opcode.c#740 https://lxr.room11.org/xref/php-src%40master/Zend/zend_operators.c#897 https://lxr.room11.org/xref/php-src%40master/Zend/zend_hash.c#1915

【问题讨论】:

  • 您比较的两个代码做的事情不同。特别是,$list[] = [$i => [$i]] 应该是 $list[$i] = [$i] 还是 $list[] = [$i]
  • 您在基准代码中的哪个位置应用了数组联合?
  • @NikiC 啊...你是对的!!!我非常专注于 PHP 内部,不知怎么地忽略了这个错误。这就解释了当我创建一个索引太高 ($i) 而不是索引为 0 的数组时需要双倍内存!好的,内存错误已修复。现在它是有道理的。我对 UNION 的理论是正确的吗?你会在数组合并部分添加一些额外的解释吗?我添加了一些可能有用的 ZEND 链接。 Revo 你会怎么称呼:“list[$i] = [$i]”?
  • @EnchanterIO array_merge 和 []= 之间的相关区别是 array_merge 复制数组而 []= 不复制(除非需要增加容量)。这就是为什么 array_merge 是 O(n) 而 []= 是(摊销) O(1)。循环运行,这就是 O(n^2) 和 O(n) 的区别。到那时,具体的实现细节就不再重要了。
  • 实际上经过进一步检查后,我意识到我之前的基准测试具有误导性,并且在@NikiC 的某些现实生活场景中几乎没有使用过。请检查我的答案,了解更多详细信息和第二个基准 Niki。

标签: php performance memory cpu internals


【解决方案1】:

我认为我的基准测试是不公平的,因为(希望没有常识的人)会遍历一个数组,然后使用 array_merge 来合并 一个 元素。

我创建了一个新的benchmark,展示了使用 foreach 和手动添加 和使用 array_merge 将 2 个大数组合并为一个之间的区别。

结果

与使用 array_merge 合并两个数组相比,手动合并两个数组没有性能优势。

【讨论】:

    猜你喜欢
    • 2011-07-11
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多