我们的一个定期运行的脚本中存在严重的内存泄漏,这些脚本会迅速清除服务器上的可用内存。尽管进行了许多小时的研究和实验,但我甚至无法在其中做出改变。PHP XML内存泄漏?
下面是代码:
echo '1:'.memory_get_usage()."\n";
ini_set('memory_limit', '1G');
echo '2:'.memory_get_usage()."\n";
$oXML = new DOMDocument();
echo '3:'.memory_get_usage()."\n";
$oXML->load('feed.xml'); # 556 MB file
echo '4:'.memory_get_usage()."\n";
$xpath = new DOMXPath($oXML);
echo '5:'.memory_get_usage()."\n";
$oNodes = $xpath->query('//feed/item'); # 270,401 items
echo '6:'.memory_get_usage()."\n";
unset($xpath);
echo '7:'.memory_get_usage()."\n";
unset($oNodes);
echo '8:'.memory_get_usage()."\n";
unset($oXML);
echo '9:'.memory_get_usage()."\n";
这里是输出:
1:679016
2:679320
3:680128
4:680568
5:681304
6:150852408
7:150851840
8:34169968
9:34169448
正如你可以看到,当我们使用XPath的节点加载到一个对象,内存使用量从跳跃681,304至150,852,408。我并不担心这一点。
我的问题是,即使在销毁$ oNodes对象后,我们仍然停留在内存使用情况34,169,968。
但real问题是PHP显示的内存使用量是脚本占用内存总量的一小部分。直接从服务器上的命令行使用free -m
,我们从3,295 MB内存使用到5,226 MB - ,它永远不会回落到。每次脚本运行时,我们都会丢失2 GB的内存,并且我完全丧失了为什么或者如何修复它。
我尝试使用SimpleXML代替,但结果基本相同。我也研究了这三个线程,但没有发现他们什么,帮助:
XML xpath search and array looping with php, memory issue
我希望这是一件简单的说,我只是俯瞰。
UPDATE 11/10:它确实显示内存最终被释放。我注意到在超过30分钟后,突然一个大块再次释放。不过,显然,最近这样的速度还不够快,以防止服务器内存不足和锁定。
而且值得一提的是,我们在Red Hat 5.11上使用Apache 2.2.3运行PHP 5.3.15。我们正在努力更新所有这些更新的最新版本,因此,在升级途径的某处,我们可能会发现这个问题已得到解决。不过,在那之前做这件事真是太棒了。
试着看看有多少引用'$ oNodes'在你'unset'之前假设apache http://php.net/manual/en/features.gc.refcounting-basics.php – Machavity
,记得每个孩子都有自己的单独的内存池,如果您正在并行处理“巨大”的xml文档,则dom基础架构不会在子项之间共享。你可以设置max_requests_per_child(无论设置是什么)低,所以apache会更频繁地释放/重启孩子,这会释放一些持有的内存。 –
@Machavity:我们没有安装Xdebug。有没有办法在没有它的情况下对参考进行计数? –