PHP 数组中的内存优化

2022-08-30 15:31:21

我正在使用一个大型数组,这是一个高度图,1024x1024,当然,我被困在内存限制。在我的测试机器中,如果我愿意,我可以将mem限制增加到1gb,但是在我的只有256 ram的小型VPS中,这不是一个选择。

我一直在堆栈和谷歌中搜索,发现有几个“好吧,你使用PHP不是因为内存效率,抛弃它并用c ++重写”,老实说,这没关系,我认识到PHP喜欢内存。

但是,在 PHP 内存管理中挖掘更多内容时,我没有找到消耗每种数据类型的内存。或者,如果转换为另一种类型的数据可以减少内存消耗。

我发现的唯一“优化”技术是取消设置变量和数组,仅此而已。

使用一些PHP解析器将代码转换为c ++会解决问题吗?

谢谢!


答案 1

如果你想要一个真正的索引数组,请使用 SplFixedArray。它使用较少的内存。此外,PHP 5.3 有一个更好的垃圾回收器。

除此之外,PHP将使用比更仔细编写的C / C++等效物更多的内存。

1024x1024 整数数组的内存使用情况:

  • 标准阵列:218,756,848
  • SplFixedArray: 92,914,208

测量公式为memory_get_peak_usage()

$array = new SplFixedArray(1024 * 1024); // array();
for ($i = 0; $i < 1024 * 1024; ++$i)
  $array[$i] = 0;

echo memory_get_peak_usage();

请注意,C 中使用 64 位整数的相同数组将为 8M。

正如其他人所建议的那样,您可以将数据打包到一个字符串中。这更慢但内存效率更高。如果使用8位值,那非常简单:

$x = str_repeat(chr(0), 1024*1024);
$x[$i] = chr($v & 0xff); // store value $v into $x[$i]
$v = ord($x[$i]);        // get value $v from $x[$i]

这里的内存只有大约1.5MB(也就是说,当考虑PHP的整个开销时,只有这个整数字符串数组)。

为了好玩,我创建了一个简单的基准测试,创建1024x1024 8位整数,然后循环浏览它们一次。所有打包的版本都使用,以便用户代码看起来相同。ArrayAccess

                   mem    write   read
array              218M   0.589s  0.176s
packed array       32.7M  1.85s   1.13s
packed spl array   13.8M  1.91s   1.18s
packed string      1.72M  1.11s   1.08s

打包的数组使用本机 64 位整数(仅打包 7 个字节以避免处理有符号数据)和使用的打包字符串和 。显然,实现细节和计算机规格会对事情产生一些影响,但我希望你能得到类似的结果。ordchr

因此,虽然数组的速度提高了6倍,但它也使用了125倍的内存作为下一个最佳选择:打包字符串。显然,如果您内存不足,速度无关紧要。(当我直接使用没有类的打包字符串时,它们只比本机数组慢3倍。ArrayAccess

简而言之,总而言之,如果速度有任何问题,我会使用纯PHP以外的其他东西来处理这些数据。


答案 2

除了评论中接受的答案和建议之外,我还想建议PHP Judy数组实现

快速测试显示了有趣的结果。使用常规 PHP 数组数据结构的具有 100 万个条目的数组需要大约 200 MB。SplFixedArray使用大约90兆字节。朱迪使用8兆。权衡在于性能,Judy花费的时间大约是常规php数组实现的两倍。