有没有办法知道内存中有哪些对象以及有多少对象?
我有一个 php 脚本,它使用 Doctrine2 和 Zend 从数据库计算一些内容,并为 30.000 个用户发送一些电子邮件。
我的脚本正在泄漏内存,我想知道哪些对象正在消耗该内存,以及谁可能保留对它们的引用(因此不允许释放它们)。
我使用 php 5.3.x,所以简单的循环引用不应该是问题。
我尝试使用 xdebug 跟踪功能来获取 mem_delta 但没有成功(数据太多)。
我尝试在重要函数之前和之后手动添加 memory_get_usage 。但我得到的唯一结论是,每个用户丢失了大约 40 万个数据,3000 个用户的时间让我获得了 1Gb 的可用数据。
还有其他方法可以知道内存泄漏的位置和原因吗? 谢谢
I have a php script that uses Doctrine2 and Zend to calculate some things from a database and send some emails for 30.000 users.
My script is leaking memory and I want to know which are the objects that are consuming that memory, and if it is possible who is keeping a reference to them (thus not allowing them to be released).
Im using php 5.3.x, so plain circular references shouldn't be the problem.
Ive tried using xdebug trace capabilities to get mem_delta with no success (too much data).
Ive tried manually adding memory_get_usage before and after the important functions. But the only conclusion that I got was that I loose around 400k per user, and 3000 users times that gives me the 1Gb that i have available.
Are there any other ways to know where and why memory is leaking?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以尝试发送 10 封电子邮件,然后插入此
http:// nz.php.net/manual/en/function.get-define-vars.php
在脚本末尾或发送电子邮件后(取决于您的代码的设置方式)。
这应该告诉您哪些内容仍在加载,以及哪些内容可以取消设置/变成参考。
另外,如果加载了两个很多东西,您将在代码的开始和结束附近得到这个并找出差异。
You could try sending say 10 emails and then inserting this
http://nz.php.net/manual/en/function.get-defined-vars.php
At the end of the script or after the email is sent (depending on how your code is setup).
This should tell you what is still loaded, and what you can unset / turn into a reference.
Also if there are two many things loaded you get this near start and end of your code and work out the difference.
30.000 个物体需要水合,这已经是相当多了。 Doctrine 2 是稳定的,但是存在一些 bug,所以我对你的内存泄漏问题并不太感到惊讶。
尽管数据集较小,但我使用学说取得了一些成功 批处理功能并创建可迭代的结果。
您可以使用示例中的代码,并在每次迭代后添加
gc_collect_cycles()
。您必须对其进行测试,但对我来说,大约 100 左右的批量大小效果非常好 - 这个数字在性能和内存使用之间提供了良好的平衡。脚本能够识别处理了哪些实体,以便可以毫无问题地重新启动并恢复正常操作,而无需发送电子邮件两次,这一点非常重要。
无论如何,也许您应该重新考虑一下该脚本的架构,因为 ORM 不太适合处理大块数据。也许您可以不用处理原始 SQL 行?
30.000 objects to hydrate is quite a lot. Doctrine 2 is stable, but there are some bugs, so I am not too surprised about your memory leak problems.
Although with smaller data sets I had some good success using doctrines batch processing capabilities and creating an iterable result.
You can use the code from the examples, and add a
gc_collect_cycles()
after each iteration. You have to test it, but for me batch sizes around 100 or so worked quite good – that number gave a good balance between performance and memory usage.It´s quite important that the script recognizes which entities where processed so that it can be restarted without any problems and resume normal operation without sending emails twice.
Anyhow, maybe you should rethink your architecture for that script a bit, as a ORM is not well suited for processing large chunks of data. Maybe you can get away with working on the raw SQL rows?