Doctrine Paginator填补了记忆

时间:2017-09-25 16:35:26

标签: php symfony memory-management doctrine-orm pagination

我有一个使用PHP 7.0.22上的Doctrine Paginator的Symfony命令。该命令必须处理来自大表的数据,因此我以100个项目的块来处理。问题是,在几百个循环后,它将填充256M RAM。作为针对OOM(内存不足)的措施,我使用:

  • $em->getConnection()->getConfiguration()->setSQLLogger(null); - 禁用sql logger,用于运行许多sql命令的脚本的记录查询来填充内存
  • $em->clear(); - 在每个循环结束时从Doctrine中分离所有对象

我已经使用memory_get_usage()放置了一些转储来检查发生了什么,看起来收集器并不像每次{{1}命令添加的那样清理打电话。

我甚至尝试用$paginator->getIterator()->getArrayCopy();每次循环手动收集垃圾,但仍然没有区别,命令开始使用18M并且每几百项增加~2M。还尝试手动取消设置结果和查询构建器......没有。我删除了所有数据处理,只保留了select查询和paginator,并得到了相同的行为。

任何人都知道我接下来要去哪看?

注意: 256M对于此类操作应该绰绰有余,所以请不要推荐建议增加允许内存的解决方案。

条带化gc_collect_cycles()方法看起来像这样:

execute()

1 个答案:

答案 0 :(得分:0)

内存泄漏是由Doctrine Paginator生成的。我使用Doctrine prepared statements将其替换为原生查询并修复它。

您应该考虑的其他事项:

  • 如果要更换Doctrine Paginator,则应通过在查询中添加限制来重建分页功能。
  • 使用--no-debug标记或-env=prod或两者同时运行您的命令。问题是命令在dev环境中默认运行。这使得一些未在prod环境中使用的数据收集器成为可能。请参阅Symfony documentation - How to Use the Console
  • 中有关此主题的更多信息

编辑:在我的特定情况中,我还使用了实现HTTP Guzzle库的捆绑eightpoints/guzzle-bundle(在我的命令中有一些API调用)。这个捆绑包也在泄漏,显然是通过一些中间件。为了解决这个问题,我必须独立地实例化Guzzle客户端,而不使用EightPoints捆绑包。