在OutOfMemory异常上有PHP转储堆

时间:2010-10-25 11:52:34

标签: php debugging heap out-of-memory dump

我目前正在调试一个不断遇到OutOfMemory异常的脚本。它作为cronjob运行并且通常运行正常,但是当cronjob运行一段时间(无论出于何种原因)时,脚本必须处理排队的许多元素并将遇到OutOfMemory异常。

从检查代码我无法发现问题。我相信其中一个迭代函数调用可能会泄漏内存,但我不确定哪一个和哪里。 发生OutOfMemory异常时,是否有选项可以让PHP转储堆?我也许能够从那里发现问题(最有可能)。

6 个答案:

答案 0 :(得分:5)

虽然我无法找到“异常转储堆”选项,但我确实发现get_defined_vars(),如果从全局范围调用,它基本上是一个堆转储。使用这个,我能够看到在我的记忆中有数百(实际上是数千)仍然引用的数据库行。这是由于臭名昭着的函数中某处未释放的mysql结果资源导致泄漏。我发现并修复了它。它现在运行良好。

答案 1 :(得分:1)

嗯,最简单的方法是在脚本中可能发生错误的部分周围使用try-catch块,并且必须在catch部分中转储堆栈。问题可能是机器人无法做出反应导致内存已满并终止。我不知道是否有助于丢弃一些变量以释放一些mermory来输出一些数据。

编辑:为此,请使用php函数debug-backtrace。这将为您提供堆栈跟踪。因此,如果机器仍在运行,很可能会发现错误。

答案 2 :(得分:0)

只是不要将所有对象一起加载到内存中,而是将它们作为进程读取它们吗?

答案 3 :(得分:0)

我在simpleXML和内存泄漏方面遇到了很多问题。他们是一个痛苦的追踪...花了我几天才弄清楚simpleXML导致然后修复它们。 据我所知,你以编程方式为OOM设置了一个处理:)

另外,PHP显示内存信息的功能无法检测到内存泄漏,我的脚本耗尽了大约1Gb的内存,但是PHP的功能报告只使用了100Mb:)

答案 4 :(得分:0)

这与'堆转储'一样好,因为我能够快速用PHP编写。我获取已定义的变量和函数,然后按序列化长度排序。序列化长度不是获得变量大小的100%可靠方法,但它非常好,通常可用于确定哪些对象是您的内存耗尽:

$memmap = array_map(function($var) { return strlen(serialize($var)); }, array_merge(get_defined_functions(), get_defined_vars())); arsort($memmap); var_dump($memmap);

如果您希望结果更详细,或者通过定义的变量进行递归,您可能需要稍微调整一下回调函数。

答案 5 :(得分:0)

我从未见过PHP为此提供本机设施,但可能存在其他一些事情:

尝试:https://github.com/mcfunley/php-heap/blob/master/php-heap.py

也可以写一个扩展来实现同样的目标。