PHP数组中的内存优化

PHP数组中的内存优化,php,arrays,memory-management,Php,Arrays,Memory Management,我使用的是一个大数组,它是一个高度图,1024x1024,当然,我的内存有限。在我的测试机器中,如果我愿意的话,我可以将内存限制提高到1gb,但是在我只有256 ram的小型VPS中,这不是一个选项 我一直在stack和google中搜索,发现了几个“好吧,你使用PHP不是因为内存效率,放弃它,用c++重写吧。”老实说,没关系,我知道PHP喜欢内存 但是,当深入了解PHP内存管理时,我并没有发现每种数据类型消耗的内存是什么。或者,如果转换到另一种类型的数据可以减少内存消耗 我发现的唯一“优化”技

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

我一直在stack和google中搜索,发现了几个“好吧,你使用PHP不是因为内存效率,放弃它,用c++重写吧。”老实说,没关系,我知道PHP喜欢内存

但是,当深入了解PHP内存管理时,我并没有发现每种数据类型消耗的内存是什么。或者,如果转换到另一种类型的数据可以减少内存消耗

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

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


谢谢

如果需要真正的索引数组,请使用。它使用更少的内存。另外,PHP5.3还有一个更好的垃圾收集器

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

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

  • 标准阵列:218756848
  • SplFixedArray:92914208
通过
memory\u get\u peak\u usage()测量

这里的内存大约只有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以外的东西来处理这些数据。

除了评论中公认的答案和建议之外,我还想提出一些建议


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

晚了一点,但是如果您有一个多维数组,那么在将整个数组存储为json时,可以节省大量RAM

$array = [];

$data = [];
$data["a"] = "hello";
$data["b"] = "world";
要存储此阵列,只需使用:

$array[] = json_encode($data);
而不是

$array[] = $data;
如果您想拿回arrry,只需使用以下方法:

$myData = json_decode($array[0], true);
我有一个275000台的大阵列,节省了大约36%的内存消耗

编辑: 在压缩json字符串时,我找到了一种更好的方法:

$array[] = gzencode(json_encode($data));
并在需要时将其解压缩:

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

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

在PHP中,数组确实需要大量内存(因为它们实际上是字典)。如果你可以放弃一些(很多!)的速度,你也可以,我想2D结构也是如此。但也许你真的想调查一下,你需要削减多少内存?正如您所读到的,在内存管理方面,在PHP中几乎没有什么可以做的。你可以进行一些“优化”,但可能没有什么能像你所需要的那样减少。PHP中的每个变量都有与之相关的开销。不仅要存储变量的值,还要存储变量的名称、类型等。。。即使是一个简单的
$x[1]=2
后面有大量的额外内容。@mario我想知道为什么链接的帖子停止了十六进制编码,而没有直接使用字符串的完整字节。看起来一点数学其实可以更快。。。但是我不使用PHP(它不会考虑有效的多字节序列等等:-)@pst:我确实有另一个版本使用
pack()
处理二进制字符串。但这并不是真的更快;只需节省两倍的内存。(在PHP中只能伪造这么多;)+1此外,模拟数组索引和使用打包可以进一步减少内存使用量(如果适用)。例如,如果每个高度映射值仅为8位,则当压缩为32位(或64位,取决于PHP位数)时,内存使用量应大大减少。效率的确切增益因有效负载大小/利用率与所用PHP值的值维护开销而不同。(我认为每个整数值有4个字节的“开销”,但我不完全确定。)显然有超过4个字节的开销。。。建议仅对于一个微不足道的值,它可能需要36(或x64上的72)字节以上。这表明打包是非常有益的(在内存使用方面)。假设8位输入和32位arch,如果打包,4个值将占用约36字节而不是约144字节,而在x64机器上,8个值将占用约72字节而不是约576字节!(哎呀!)所以,最后。。。通过打包,8位值被摊销到~9字节,用于即时估算9MB的对象开销/数据,不包括包含在数组本身中所需的内存等——将公布的数字四分之一的总使用量约为22.5MB。(这种打包可能看起来过于优化,但考虑到目标限制为256MB RAM…-)@pst,我添加了一些关于将数据打包成字符串的内容。当处理8位整数(可能是高度映射)时,字符串整数数组的大小基本上与C等价物的大小相同。当然,速度会比本机整数差得多。@konforce Packing in a PHP integral value:)对于许多操作(仅一个ma),速度应该接近非压缩
$array[] = gzencode(json_encode($data));
$myData = json_decode(gzdecode($array[0], true));