我有一个拥有大量人员的PHP脚本,它通过SOAP从外部资源中获取其详细信息,修改数据并将其发回.由于细节的大小,我将PHP的内存增加到128MB.运行大约4个小时后(运行可能需要4天),内存不足.以下是它的基本知识:
$people = getPeople();
foreach ($people as $person) {
$data = get_personal_data();
if ($data == "blah") {
importToPerson("blah", $person);
} else {
importToPerson("else", $person);
}
}
在内存耗尽并崩溃之后,我决定在foreach循环之前初始化$data,并且根据顶部,进程的内存使用率没有超过7.8%并且已经运行了12个小时.
所以我的问题是,即使重用,PHP也不会对循环内初始化的变量运行垃圾收集器吗?系统是否回收内存并且PHP还没有将其标记为可用并且最终会再次崩溃(我现在已经将它升级到256MB所以我已经改变了2件事并且不确定哪个已修复它,我可能会改变我的脚本回来回答这个,但又不想再等12个小时让它崩溃才弄清楚)?
我没有使用Zend框架,所以像我这样的其他问题我认为不相关.
编辑:我实际上没有脚本的问题或它正在做什么.目前,就所有系统报告而言,我没有任何问题.这个问题是关于垃圾收集器以及它如何/何时回收foreach循环中的资源和/或系统如何报告php进程的内存使用情况.
解决方法:
我不知道PHP的VM的内部,但根据我的经验,它不会在您的页面运行时进行垃圾收集.这是因为它会丢弃页面完成时创建的所有内容.
大多数情况下,当页面内存不足且限制非常高(并且128Mb不高)时,会出现算法问题.许多PHP程序员组装了一个数据结构,然后将其传递给下一步,迭代结构,通常创建另一个结构.泡沫,冲洗,重复.不幸的是,这种方法是一个很大的内存耗尽,最终你会在内存中创建多个数据副本. PHP 5中的两个非常大的变化是对象被引用计数,而不是被复制,并且整个字符串子系统的制作速度要快得多.但它仍然是一个问题.
为了最大限度地减少内存使用,您需要重新构建算法,以便它可以从头到尾处理一个数据.然后你得到下一个并重新开始.最好的情况是你没有在内存中拥有整个数据集.对于数据库支持的网站,这意味着在获得下一个数据库之前处理从数据库查询到呈现的一行数据.当然,这种方法并不总是可行的,脚本只需要在内存中保留大量的数据.
也就是说,您可以为部分数据执行这种节省内存的方法.诀窍是你在循环结束时显式取消设置一个或两个键变量.这应该回收空间.另一个“最佳实践”技巧是转移出不需要在循环中的循环数据操作.你似乎已经发现了.
我运行的PHP脚本需要超过1Gb的内存.实际上,您可以使用ini_set(‘memory_limit’,’1G’)设置每个脚本的内存限制;