你如何调试php"Out of Memory"问题?

Kev*_*cki 29 php memory debugging methodology

我最近遇到了一些关于PHP内存限制的问题:

内存不足(分配22544384)(试图分配232个字节)

这些都是调试的麻烦,因为我没有留下关于导致问题的原因的大量信息.

添加关机功能有所帮助

register_shutdown_function('shutdown');
Run Code Online (Sandbox Code Playgroud)

然后,使用error_get_last(); 我可以获取有关上一个错误的信息,在这种情况下,"内存不足"致命错误,例如行号和php文件名.

这很好,但是我的php程序非常面向对象.堆栈深处的错误并没有告诉我有关错误时控制结构或执行堆栈的信息.我已经尝试过debug_backtrace(),但这只是在关机期间向我显示堆栈,而不是错误发生时的堆栈.

我知道我可以使用ini_set或修改php.ini来提高内存限制,但这并没有让我更接近实际找出消耗如此多内存的内容或错误期间执行流程的样子.

任何人都有一个很好的方法来调试高级面向对象的PHP程序中的内存错误?

Nic*_*ing 11

echo '<pre>';
$vars = get_defined_vars();
foreach($vars as $name=>$var)
{
    echo '<strong>' . $name . '</strong>: ' . strlen(serialize($var)) . '<br />';
}
exit();

/* ... Code that triggers memory error ... */
Run Code Online (Sandbox Code Playgroud)

我使用它在我的代码的问题部分之前打印出当前分配的变量列表,以及对变量大小的(非常)粗略估计.我会回到unset任何在兴趣点之外不需要的东西.

当安装扩展程序不是一个选项时,它很有用.

您可以修改上面的代码,以便memory_get_usage在变量中给出不同的内存估计值,不确定它是好还是坏.


小智 7

Memprof是一个php扩展,可​​以帮助找到那些内存消费者片段,特别是面向对象的代码.

这个改编的教程非常有用.

注意:我没有成功尝试为Windows编译此扩展.如果您这样做,请确保您的PHP不是线程安全的.为了避免一些麻烦,我建议你在*nix环境下使用它.

另一个有趣的链接是描述php如何处理内存的幻灯片.它为您提供了有关脚本内存使用情况的一些线索.


And*_*ber 6

我想知道也许你的思考问题方法在这里是有缺陷的.

您的问题的基本答案 - 如何找出此错误发生的位置? - 已经回答; 你知道是什么造成的.

但是,这是触发错误实际上不是问题的情况之一 - 当然,232字节对象根本不是你的问题.这是在它之前分配的20 + Megs.

已发布一些想法可以帮助您追踪这一点; 你真的需要在应用程序架构中看到"更高级别",而不仅仅是单个函数.

可能是您的应用程序需要更多内存来执行它所做的事情,并且您拥有用户负载.或者可能有一些真正的记忆力是不必要的 - 但你必须知道什么是必要或不回答这个问题.

这基本上意味着逐行,逐个对象,根据需要进行分析,直到找到你想要的东西; 大内存用户.请注意,可能没有一个或两个大项目......如果只是它那么容易!找到内存后,你必须弄清楚它们是否可以优化.如果没有,那么你需要更多的记忆.

  • 它不一定是架构问题.你可以通过偶然的无限递归或无限循环来避免内存错误,无论你分配多少,都会占用所有**内存. (2认同)

小智 2

查看函数memory_get_usage()的文档来查看运行时的内存使用情况。

  • 谢谢。我知道内存_get_usage(),但在我的代码库中随意删除它们并希望我能捕获内存使用量的峰值似乎有点草率和低效。不过,我对使用此函数的方法很感兴趣。 (3认同)