【问题标题】:Is there a way to know which objects and how many of them do i have in memory?有没有办法知道我在内存中有哪些对象以及它们中有多少?
【发布时间】:2011-10-05 23:30:48
【问题描述】:

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

我的脚本正在泄漏内存,我想知道哪些对象正在消耗该内存,以及是否有可能谁在保留对它们的引用(因此不允许释放它们)。

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

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

我尝试在重要功能之前和之后手动添加 memory_get_usage。但我得到的唯一结论是,我每个用户损失了大约 400k,而 3000 个用户的时间给了我可用的 1Gb。

还有其他方法可以知道内存泄漏的位置和原因吗? 谢谢

【问题讨论】:

  • 嗯,用户应该是一个接一个的处理,应该只需要400k的内存!如果每个周期都增加了内存使用量,那么您的设计中的某些地方就大错特错了!
  • 好吧,我有一个循环调用一个函数,该函数执行以下操作:获取用户信息、计算(包括存储)、发送邮件、释放资源。而且每个用户都是相互独立的,所以资源显然没有被释放
  • 你看过学说的 entitymanager 了吗?我对原则不是很熟悉,但它可能会为所有 30k 用户存储对实体/代理/...的引用。
  • 您尝试过 xdebug 分析器吗?它应该让您很好地了解哪种方法占用的内存最多。 xdebug.org/docs/profiler
  • @Fge 在计算完每个用户后我对实体管理器做了一个清除,所以据我所知应该是去掉

标签: php zend-framework memory-leaks doctrine-orm php-5.3


【解决方案1】:

您可以尝试发送 10 封电子邮件,然后插入此邮件

get_defined_vars();

http://nz.php.net/manual/en/function.get-defined-vars.php

在脚本结束或发送电子邮件后(取决于您的代码的设置方式)。

这应该告诉您哪些内容仍在加载,哪些内容可以取消设置/转为参考。

此外,如果加载了两个很多东西,您可以在代码的开始和结束附近得到这个并计算出差异。

【讨论】:

  • 谢谢,这似乎很有帮助。我会在我的循环中尝试。从文档中,唯一让我担心的是它只给我关于范围内对象的信息。而且我猜测内存问题之所以存在,是因为它超出了范围。
【解决方案2】:

30.000 个需要水合的物体是相当多的。 Doctrine 2 是稳定的,但有一些错误,所以我对你的内存泄漏问题并不感到惊讶。

尽管使用较小的数据集,我在使用 batch processing 功能并创建可迭代结果方面取得了一些成功。

您可以使用示例中的代码,并在每次迭代后添加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 行的处理?

【讨论】:

    【解决方案3】:

    这不是一个可以为您提供所需的工具,但也许它会帮助您。如果您还没有,您可以实现身份映射模式,每次创建对象时,它都会向身份映射注册,因此您可以随时调用 IM 并查看加载了哪些对象或告诉它卸载任何对象加载对象。

    http://martinfowler.com/eaaCatalog/identityMap.html

    【讨论】:

    • @Joey_Rivera 该模式已经由学说实现,如果在查询时需要性能,我会使用它,我的问题是相反的。我不需要添加更多对对象的引用,我需要一种减少引用计数的方法。
    猜你喜欢
    • 2013-09-10
    • 2023-03-10
    • 2011-07-31
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2020-09-11
    • 2019-11-12
    • 2020-09-08
    相关资源
    最近更新 更多