我有一个无限长运行的 PHP 脚本(无限主事件循环)处理来自 Twitter 的传入推文流并将它们存储到 MySQL。但是,我似乎无法控制它的内存使用情况。我发现了 3 种测量内存使用情况的方法:
memory_get_usage()
- 报告大约 4.0 MBmemory_get_usage(true)
- 报告大约 7.5 MBexec("ps -o rss -p ".getmypid(), $memOutput);
- 报告一个线性增加的数字,该数字在 60 分钟或更短时间内迅速增长到数百 MB,并且继续消耗内存,直到脚本被强制终止。
我的问题:
1) 这三种措施之间的实际区别是什么?
但主要是:
2) 如果前两个相对恒定,但第三个方法像这样疯狂失控,这意味着什么?
FWIW,我正在使用 PHP 5.3 和 Zend Framework 1.x 以及大量 Zend_Db 事件。脚本在 CLI SAPI 下运行。 Zend_Db_Profiler 没有被使用。我还有第二个无限运行的脚本,它根本不使用数据库,并且内存使用量是恒定的。所以它似乎与数据库有关,也许是我的 PHP 设置正在使用的 MySQL 扩展,或者可能是 Zend_Db。我在自己的代码中煞费苦心地避免粗心大意地缓存对象,尽管我还没有对 Zend 的代码本身这样做。
我已经尝试让我的脚本调用 gc_enable()
,并定期运行 gc_collect_cycles()
,但这没有帮助。
有什么想法吗?
编辑 我打算尽快分析这段代码,但与此同时我注意到即使我不接触数据库的脚本也在泄漏内存。但它们这样做的速度要慢得多,只有在比较几天的内存使用情况时才会变得明显。
最佳答案
好吧,我无法在这里为您指出确切的答案,因为您需要自己进行分析。从你所说的来看,它似乎指向 Zend 的 DB 层,但是除非你对此进行分析,否则你无法确定。 ;)
在 UNIX/Linux 上(我希望您以正确的方式运行 PHP - UNIX/Linux 方式:D)有一些非常有用的工具可用于在系统级别 分析此类应用程序并检查PHP 应用程序中的实例化和内存消耗。 您可以使用 Valgrind获取一些信息,例如:
valgrind --tool=callgrind --dump-instr=yes -v --instr-atstart=no /usr/sbin/apache2 -X
注意 Valgrind 是一个 suite of tools在这里我们使用“callgrind”工具 - 它
provides all the information that Cachegrind does, plus extra information about callgraphs
这将创建一个 callgrind.out
文件或一组我不记得的文件。
无论如何,您现在可以使用 Kcachegrind可视化收集的信息:
kcachegrind callgrind.out
您将看不到调用的可视化以及应用程序特定部分使用的内存百分比。就像是:
您还可以尝试 Valgrind 套件中的其他一些工具,例如 Memcheck看
all reads and writes of memory and calls to malloc/new/free/delete
我第一次了解 Valgrind 是在尝试分析我的 Linux 服务器时。然后我研究了一下,结果发现它是一个非常好的分析 PHP 应用程序的工具......有 a very good talk on this here .我使用了那里的一些例子。检查一下!
在您介绍您的应用程序之后,请返回有关它是什么的信息,或者您看到了什么等等。我将很乐意对此进行分析。希望这有所帮助。 ;)
编辑: 我现在想起来我错过了一些东西。 :D 您也可以尝试使用 APD这是一个 zend 扩展和 could also provide useful information .我没有亲自使用过它,但互联网上有一些很好的例子。
另一个选项是 Xhprof - 层次分析器。你可以用它来 gather different metrics .最后应该结合使用这些工具。如何以及为什么取决于您。
关于php - 解决 PHP 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18524984/