2013-08-30 156 views
4

我有一个运行无限长(无限主事件循环)处理来自Twitter的鸣叫传入的流,并将其存储到MySQL的PHP​​脚本。但是,我似乎无法控制其内存使用情况。我发现3种方式来衡量内存使用:解决PHP内存泄漏

  • memory_get_usage() - 约4.0 MB
  • memory_get_usage(true)报告 - 报告约7.5 MB
  • exec("ps -o rss -p " . getmypid(), $memOutput); - 报告线性增加的数量快速增长到数百MB在60分钟或更短的时间内,并继续吞噬内存,直到脚本被强行终止。

我的问题:

1)什么是这三个措施之间的实际差别?

但主要是:

2)什么意思,如果前两个是相对恒定的,但第三个方法是疯狂了这样的控制?

FWIW,我使用PHP 5.3与Zend框架1.x和很多Zend_Db的活动。脚本在CLI SAPI下运行。 Zend_Db_Profiler没有被使用。我还有第二个无限制运行的脚本,它根本不使用数据库,并且内存使用情况不变。因此,它似乎是与数据库相关的,也许是MySQL扩展我的PHP安装使用,也可能Zend_Db的。我已经在我自己的代码中不厌其烦地避免不小心缓存的对象,虽然我还没有与Zend的代码本身做到了这一点。

我试过让脚本调用gc_enable(),并定期运行gc_collect_cycles(),但这没有帮助。

任何想法?

编辑我打算只要我可以分析这个代码,但同时我也注意到,即使我的脚本不碰DB也被泄漏内存。但是他们的速度要慢得多,只有在几天的时间内比较内存使用情况才会显现出来。

+1

在不需要对象之后,为了回收内存,您已经采取了哪些步骤? –

+1

首先,我通过使用数组来瞬间存储数据,从而避免使用对象。但关于对象(比如Zend_Db返回的表行),我没有做任何特殊的事情来回收它们的内存。我的理解是,当它们超出范围(即方法结束时),并且不再引用这些对象时,它们便有资格通过PHP的垃圾回收进行回收。我不保留任何引用。但我意识到Zend_Db可能是。 – curtisdf

回答

2

好,因为你需要做的剖析自己,我不能指向你确切的答案在这里。从你所说的看来,Zend的数据库层看起来很不错,但除非你对此进行简要描述,否则你无法确定。 ;)

在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”工具 - 它

提供的所有信息Cachegrind,加上关于调用图的额外信息

这将创建一个callgrind.out文件或一组我不记得的文件。 反正你现在可以使用Kcachegrind可视化所收集的信息:

kcachegrind callgrind.out 

,你会看到没有来电的可视化和存储您的应用程序的某一部分使用的百分比。喜欢的东西: Wordpress memory profile

您也可以尝试一些在Valgrind的套件一样Memcheck其他工具来查看

所有读取和存储器的写入和调用malloc /新/免费/删除

我第一次了解Valgrind时试图剖析我的Linux服务器。然后我研究了一下,结果发现它是一个非常好的工具来分析PHP应用程序......有a very good talk on this here。我使用了一些例子。一探究竟!

并且在你分析你的应用程序后,请回来一些关于它是什么的信息,或者你看到了什么等。我将会非常有趣地分析这个。希望这有助于。 ;)

编辑: 我现在记得我错过了一些东西。 :D 您也可以尝试使用APD这是一个zend扩展和could also provide useful information。我没有亲自使用过它,但互联网上有一些很好的例子。

另一个选项是Xhprof - 分层分析器。你可以用这个来gather different metrics。最后应该使用这些工具的组合。如何和为什么取决于你。

+1

感谢鲍里斯拉夫的指点。我没有机会尝试他们,但是当我有机会时我会。同时我重写了我的脚本,因此与数据库相关的部分被称为单独的短暂进程。这有效地解决了内存问题。 – curtisdf

+0

PHP的用户空间内存使用函数显示稳定和可预测的值,但仍然令人费解,而只有外部进程显示的内存使用情况(例如命令行中的“ps”)才是失控的。这让我觉得它可能根本不是用户登陆的PHP代码,但也许是PHP或我正在使用的一些扩展的较低级别问题。使用您提到的工具来分析代码会非常有趣。 – curtisdf

+0

@curtisdf确实如此。描述这一点将是非常有趣的。 你愿意分享数据吗?它不会包含任何代码。它也可能真的是一些外部实体。 无论如何,PHP是一种脚本语言,由于其设计,长时间运行的脚本一直是个问题。 其他要尝试的事情之一是“异步PHP” - [作为示例反应](http://reactphp.org/)。它可能是基于事件的长时间运行脚本的解决方案。 –