PHP数组中的内存优化

时间:2011-06-13 21:21:54

标签: php arrays memory-management

我正在使用一个大型数组,这是一个高度图,1024x1024,当然,我仍然坚持内存限制。在我的测试机器中,如果我想要的话,我可以将内存限制增加到1GB,但在我只有256内存的微小VPS中,它不是一个选项。

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

但是,当在PHP内存管理中挖掘更多内容时,我没有发现每种数据类型占用的内存。或者,如果转换为其他类型的数据会减少内存消耗。

我发现唯一的“优化”技术是取消设置变量和数组,就是这样。

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

谢谢!

3 个答案:

答案 0 :(得分:47)

如果您想要一个真正的索引数组,请使用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();

请注意,使用64位整数的C中的相同数组将是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倍的内存作为下一个最佳替代方案:打包字符串。显然,如果你的内存不足,速度是无关紧要的。 (当我在没有ArrayAccess类的情况下直接使用压缩字符串时,它们只比原生数组慢3倍。)

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

答案 1 :(得分:11)

除了评论中接受的答案和建议外,我还建议PHP Judy array implementation

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

答案 2 :(得分:0)

聚会晚了一点,但是如果您有多维数组,则将完整数组存储为json时可以节省大量RAM。

$array = [];

$data = [];
$data["a"] = "hello";
$data["b"] = "world";

要存储此数组,请使用:

$array[] = json_encode($data);

代替

$array[] = $data;

如果您想找回押金,只需使用以下内容:

$myData = json_decode($array[0], true);

我有一个包含275.000套的大型阵列,并节省了约36%的RAM消耗。

编辑: 当您压缩json字符串时,我发现了一种更好的方法:

$array[] = gzencode(json_encode($data));

并在需要时将其解压缩:

$myData = json_decode(gzdecode($array[0], true));

这为我节省了将近75%的RAM峰值使用率。