PHP在阵列操作期间突然增加内存使用量

时间:2013-12-22 08:57:35

标签: php arrays memory memory-management

我正在用PHP编写维护脚本。该脚本在关联数组中保留大约100,000个键值对,并将一堆其他数据与该数组进行比较。

键是12或16字节的十六进制字符串。

值是包含1-10个字符串的数组。每个字符串大约50个字节。

我通过循环中的fgets()逐行阅读文本文件来填充我的数组。

一切正常,直到我达到大约44,000个键,但之后内存使用量突然猛增。

无论我增加多少内存限制(目前我还不愿意给它超过256MB),内存使用量会呈指数级增长,直到达到新的限制。这很奇怪!

以下是左侧按键数量和右侧内存使用情况的表格。

10000     6668460
20000    12697828
30000    18917768
40000    25045068
41000    25658148
42000    26760304
43000    27350368
44000    27920400
45000    33438520
46000    77800344
47000   114203960
48000   161989660
49000   168419992
50000   206265572
Fatal error: Allowed memory size of 268435456 bytes exhausted

正如您所看到的,内存使用情况在每个密钥 620-660字节时保持一致,直到我达到44,000个密钥。之后,内存使用量突然开始增加,直到达到每个密钥超过4KB 50,000个密钥。这很奇怪,因为我的键和值的大小总是相似的。

似乎我对数组中可以拥有的键数量有某种内部限制,超出这个限制,这一切都变得非常低效。

如果我可以保持每个键620-600字节的内存使用量(考虑到使用数组的通常开销,这听起来很合理),我的整个数据集应该适合大约。 64MB的内存,因此在我稍后需要在同一个脚本中引用它时可以轻松访问。这是我第一次开始编写脚本时的假设。这是一个从CLI运行的维护脚本,因此可以不时使用64MB的内存。

但如果内存使用率如上所述持续增长,我别无选择,只能将键值数据集卸载到外部守护程序,如Memcached,Redis或SQL数据库,网络开销将大大减慢维护脚本。

到目前为止我尝试了什么:

  • 我尝试将二维数组展平为多个一维数组。没有运气。
  • 我尝试将大数组拆分成多个较小的数组。没有运气。
  • 我尝试根本不使用数组并将每个键转换为单独的变量。没有运气。
  • 我不能使用SplFixedArray,因为我的键不是数字(并且不能转换为整数范围内的数字),并且数组需要是可变的。
  • 我宁愿不使用Quickhash,Judy或任何其他以C扩展名编写的替代数组实现。
  • 抱歉,这个脚本需要使用PHP。不要问我为什么......

测试服务器是运行Ubuntu 12.04 LTS的虚拟机,32位,PHP 5.3.10-1ubuntu3.9。

有什么想法吗?

  • 这是在更新版本的PHP中修复的内容吗?
  • 我应该只将数据集提供给外部守护程序,例如Memcached吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

我认为这是垃圾收集。在某些时候,你正在使用分配临时空间的操作,然后在努力工作期间无法释放,因此php将耗尽你的记忆而不是真正的目的。

当我遇到这个问题时,我终于得出结论,垃圾只在特定事件中被丢弃,就像退出一个函数一样。所以你应该尝试的是,让你的工作分成几个较小的步骤,让你的变量在它们之间“放松” - 制作一个只能一次完成一千个元素的函数,然后再次调用它继续它停止的地方。

希望这会有所帮助。

相关问题