有没有办法知道内存中有哪些对象和它们的个数


Is there a way to know which objects and how many of them do i have in memory?

我有一个php脚本,使用Doctrine2和Zend从数据库中计算一些东西,并为30,000用户发送一些电子邮件。

我的脚本正在泄漏内存,我想知道哪些对象正在消耗内存,如果可能的话,谁在保持对它们的引用(因此不允许它们被释放)。

我使用php 5.3。X,所以简单的循环引用应该不是问题。

我尝试使用xdebug跟踪功能来获取mem_delta,但没有成功(数据太多)。

我尝试在重要函数之前和之后手动添加memory_get_usage。但我得到的唯一结论是,我每个用户损失了大约400k, 3000个用户乘以这个,我就有了1Gb的可用空间。

是否有其他方法知道内存泄漏的位置和原因?由于

你可以试着发送10封邮件然后插入这个

get_defined_vars();
http://nz.php.net/manual/en/function.get-defined-vars.php

在脚本的末尾或在电子邮件发送之后(取决于你的代码是如何设置的)。

这应该告诉你哪些仍然被加载,哪些可以取消设置/转换为引用。

如果加载了很多东西,你可以在代码的开始和结束处设置这个,并计算出差异

3万个物体需要水合物是相当多的。原则2是稳定的,但有一些bug,所以我不太惊讶你的内存泄漏问题。

虽然对于较小的数据集,我使用doctrine批处理功能并创建可迭代的结果取得了一些成功。

您可以使用示例中的代码,并在每次迭代后添加一个gc_collect_cycles()。你必须测试它,但对我来说,批处理大小在100左右工作得很好——这个数字在性能和内存使用之间取得了很好的平衡。

这是相当重要的,脚本识别哪些实体被处理,以便它可以重新启动没有任何问题,并恢复正常的操作,而不发送两次电子邮件。

$batchSize = 20;
$i = 0;
$q = $em->createQuery('select u from MyProject'Model'User u');
$iterableResult = $q->iterate();
while (($row = $iterableResult->next()) !== false) {
    $entity = $row[0];
    // do stuff with $entity here
    // mark entity as processed
    if (($i % $batchSize) == 0) {
        $em->flush(); 
        $em->clear();
        gc_collect_cycles();
    }
    ++$i;
}

无论如何,也许您应该重新考虑一下该脚本的体系结构,因为ORM不太适合处理大块数据。也许您可以处理原始SQL行?