Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/254.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP在数组操作期间内存使用量突然增加_Php_Arrays_Memory_Memory Management - Fatal编程技术网

PHP在数组操作期间内存使用量突然增加

PHP在数组操作期间内存使用量突然增加,php,arrays,memory,memory-management,Php,Arrays,Memory,Memory Management,我正在用PHP编写一个维护脚本。该脚本在关联数组中保留大约100000个键值对,并将一组其他数据与该数组进行比较 键是12字节或16字节的十六进制字符串 这些值是包含1-10个字符串的数组。每个字符串大约有50个字节 我通过在循环中使用fgets()逐行读取文本文件来填充数组 在我按下大约44000个键之前,一切都很好,但在那之后,内存使用量突然飙升。 无论我增加多少内存限制(目前我不确定是否超过256MB),内存使用量都会成倍增加,直到达到新的限制。这太奇怪了 下表左侧为键数,右侧为内存使用情

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

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

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

我通过在循环中使用
fgets()
逐行读取文本文件来填充数组

在我按下大约44000个键之前,一切都很好,但在那之后,内存使用量突然飙升。

无论我增加多少内存限制(目前我不确定是否超过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字节,直到我达到44000个键为止。此后,内存使用量突然开始增加,直到50000个键时,每个键的内存使用量超过4KB。这很奇怪,因为我的键和值的大小总是相似的

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

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

但是,如果内存使用量像上面那样持续增加,我将别无选择,只能将键值数据集卸载到外部守护程序(如Memcached、Redis或SQL数据库),网络开销将大大降低维护脚本的速度

到目前为止我所尝试的:

  • 我尝试将二维数组展平为多个一维数组。不走运
  • 我尝试将大数组拆分为多个较小的数组。不走运
  • 我试着根本不使用数组,而是将每个键都转换成一个单独的变量。不走运
  • 我不能使用
    SplFixedArray
    ,因为我的键不是数字(并且不能转换为整数范围内的数字),数组需要可变
  • 我不希望使用Quickhash、Judy或任何其他作为C扩展编写的替代数组实现
  • 抱歉,此脚本需要使用PHP。别问我为什么
测试服务器是一个运行Ubuntu 12.04 LTS、32位、PHP5.3.10-1ubuntu3.9的虚拟机

有什么想法吗?

  • 这是PHP最新版本中修复的吗
  • 我应该把数据集交给像Memcached这样的外部守护进程吗

谢谢

我想这是垃圾收集。在某些情况下,您正在使用分配临时空间的操作,这些临时空间在繁重的工作中无法释放,因此php将毫无目的地占用您的内存

当我面对这个问题时,我最终得出结论,垃圾只在特定事件中被丢弃,比如退出函数。因此,您应该尝试的是,将工作分为几个较小的步骤,让变量在它们之间“放松”——创建一个一次只执行1000个元素的函数,然后再次调用它以继续它停止的地方


希望这有帮助

GC似乎无法解释44000个键之后内存使用突然增加的原因。如果($line=fgets($fp))循环中积累了任何垃圾,则内存使用量应保持线性增加,而不是突然增加。是的,但我看不到您的循环,也看不到您读取的文件。我不知道里面发生了什么。我可以想象一些事情,但我不想在黑暗中拍摄。例如,如果有一个fseek($x)的$x溢出,它可能会造成这样的效果。但不管它值多少钱,它只是一堆
explode(“|”),trim($line))
,其中第一部分用作键,其余部分连接成值。没有对象,没有手动搜索,只有基本的字符串操作。无论如何,谢谢你的建议。是的,你正在分析它。现在不管发生什么,您都在创建tmp阵列。试试我说的。它可能是内存碎片,这就是为什么我说它是gc。例如,内存分配中的“不足”漏洞可能会导致暴涨。是的,如果下一个临时变量大于上一个临时变量,则会出现问题。这会导致无法用下一个孔填充的孔。