我有一个使用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()
答案 0 :(得分:0)
内存泄漏是由Doctrine Paginator生成的。我使用Doctrine prepared statements将其替换为原生查询并修复它。
您应该考虑的其他事项:
--no-debug
标记或-env=prod
或两者同时运行您的命令。问题是命令在dev
环境中默认运行。这使得一些未在prod
环境中使用的数据收集器成为可能。请参阅Symfony documentation - How to Use the Console 编辑:在我的特定情况中,我还使用了实现HTTP Guzzle库的捆绑eightpoints/guzzle-bundle
(在我的命令中有一些API调用)。这个捆绑包也在泄漏,显然是通过一些中间件。为了解决这个问题,我必须独立地实例化Guzzle客户端,而不使用EightPoints捆绑包。