我正在使用一个大型数组,这是一个高度图,1024x1024,当然,我仍然坚持内存限制。在我的测试机器中,如果我想要的话,我可以将内存限制增加到1GB,但在我只有256内存的微小VPS中,它不是一个选项。
我一直在堆栈和谷歌搜索并发现了几个“好吧,你使用PHP不是因为内存效率,丢弃它并在c ++中重写”,老实说,这没关系,我认识到PHP喜欢内存。
但是,当在PHP内存管理中挖掘更多内容时,我没有发现每种数据类型占用的内存。或者,如果转换为其他类型的数据会减少内存消耗。
我发现唯一的“优化”技术是取消设置变量和数组,就是这样。
使用一些PHP解析器将代码转换为c ++可以解决问题吗?
谢谢!
答案 0 :(得分:47)
如果您想要一个真正的索引数组,请使用SplFixedArray。它使用更少的内存。此外,PHP 5.3有一个更好的垃圾收集器。
除此之外,PHP将使用更多内存而不是更精心编写的C / C ++等效内容。
1024x1024整数数组的内存使用情况:
以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个字节以避免处理签名数据),打包字符串使用ord
和chr
。显然,实现细节和计算机规格会对事情产生一些影响,但我希望你能得到类似的结果。
因此,虽然阵列速度提高了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峰值使用率。