【问题标题】:How to "drilldown" memory_get_usage() in PHP to find memory leaks?如何在 PHP 中“向下钻取”memory_get_usage() 以查找内存泄漏?
【发布时间】:2012-03-16 00:29:00
【问题描述】:

我的脚本有时会中断,因为我收到如下错误:

PHP Fatal error: Allowed memory size of X bytes exhausted (tried to allocate Y bytes) in ...

内存限制太低,设置为 128M。 (这应该绰绰有余了。)

问题是随着脚本的运行,它会占用越来越多的内存。基本上,这是一个for 循环。我检查了每个变量,但是脚本没有填充“某些东西”(例如数组)的地方,这些东西会增长并解释为什么脚本占用更多内存。

我使用memory_get_usage() 确认了内存问题。每次迭代后我都会打印出内存占用,而且数字总是更高。

目前使用 Xdebug 并没有显示出任何可以帮助我的迹象。

有什么方法可以让我深入了解每次循环时占用更多内存的原因吗?您建议如何调试这种情况?

【问题讨论】:

  • 不幸的是,没有简单的方法可以在 php 中调试内存泄漏。尝试将循环的内容放在单独的方法或函数中。所以你的循环体只不过是那个函数调用。 IIRC PHP 的垃圾收集器在函数或方法结束时被调用。由于您所拥有的只是一个循环,因此永远不会调用 GC。
  • Mike,我试过你的建议,发现调用函数与不调用函数对内存有影响。所以我知道“问题”出在那个功能上。也就是说,即使我将代码放入函数中并对每个变量执行unset(...),每次调用该函数后内存仍然会变高,直到它终止脚本。 GC 似乎对此没有影响。
  • Doh,希望有一个简单的解决方案。查看我的类似问题.. 一些答案可能会有所帮助stackoverflow.com/questions/849549/…

标签: php debugging memory memory-leaks


【解决方案1】:

简短的回答是:不可能向下钻取。

也就是说,我发现问题的方式是我将循环内的代码拆分为子函数。然后,我对它们都进行了评论,只检查循环的足迹是什么而不做任何事情。然后,我逐个函数地取消注释,直到找到有问题的那个。

一旦我得到有问题的函数,我再次执行相同的过程:注释其中的所有内容,然后取消注释,直到找到有问题的代码段。

我终于发现我正在从 PHP 调用一个使用 create_function 的函数。许多人都在“抱怨”这个函数的“内存泄漏”。问题不是内存泄漏,而是如果你在循环中调用create_function,它实际上会创建与循环次数一样多的函数。为了避免这种情况,我发现这个概念是为了避免重新创建函数数千次。

<?php 
global $my_func; 
if (!isset($my_func)) { 
    $my_func = create_function($args, $code); 
}

$my_func(); 
?>

调整代码以确保仅在解决问题后才创建函数。整个脚本现在只占用 8MB 内存,而不是在超过 128MB 后中断。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 2014-03-26
    相关资源
    最近更新 更多