我已经安装了FOSElasticaBundle并让它处理我的数据的横截面。
我的问题出现了,我需要使用大约14m行来构建索引。我运行了populate命令,在昨天大约6个小时后,它出现了10.8%的错误并出现内存错误:
PHP Fatal error: Allowed memory size of 2147483648 bytes exhausted (tried to allocate 52277 bytes) in /var/www/html/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php on line 111
正如您所看到的,我已将我的php内存限制设置为2G,这应该是相当多的。
错误前的最后一行看起来像
Populating index/entity, 10.8% (1315300/12186320), 36 objects/s (RAM : current=2045Mo peak=2047Mo)
每条线的电流和峰值都在上升,大约30mb。
我的假设是存在某种内存泄漏?当然,php的记忆不应该被这个过程所累。我还尝试了一些额外参数的命令
app/console fos:elastica:populate --no-debug --no-reset --env=prod
但是当我看着它正在运行时,当前的内存仍然在增加。
对这里可能发生的事情以及我可以做些什么来调试它的想法?我发现这个讨论听起来像我的问题,但并没有真正提供一个好的解决方案:https://github.com/FriendsOfSymfony/FOSElasticaBundle/issues/82。我使用的是doctrine和默认提供程序。
谢谢 -
答案 0 :(得分:6)
我无法完全解决内存泄漏,而是通过运行命令
app/console fos:elastica:populate --no-debug --no-reset --env=prod --offset=n
我已经能够分批填充。我使用此页面上的解决方案,通过关闭记录器来大幅减少内存泄漏量
https://github.com/FriendsOfSymfony/FOSElasticaBundle/issues/273
将我的php memory_limit设置为4G(!)我能够在没有错误的情况下填充超过500万条记录,因此在完成几个批次之后,我应该完成此过程。
大多数解决方案似乎都涉及编写自定义提供程序(请参阅https://github.com/FriendsOfSymfony/FOSElasticaBundle/issues/457),但通过一个荒谬的memory_limit并尽可能地限制内存泄漏,我并不需要。
答案 1 :(得分:1)
这里的主要问题是一切都在一个进程中完成,所有实体都必须加载到内存中。它由块完成,但仍然会加载所有数据。你可以做很多事情来解决设计中的问题。
解决方案:数据可以拆分为块,这些块在不同的进程中并行处理。工作进程可能会不时退出(它们必须由Supervisord或类似工具重新启动)释放内存和资源。因此,您将获得更好的性能和更好的容错能力以及更少的内存占用。
有很多方法可以实现这一点(使用forks,pthreads或消息队列),但我个人建议查看enqueue/elastica-bundle。它通过拆分作业和发送消息来改进populate命令。
答案 2 :(得分:0)
如果--no-debug
选项不够用,您可能要检查是否有fingers_crossed
处理程序并设置buffer_size
:
monolog:
handlers:
main:
type: fingers_crossed
action_level: critical
handler: grouped
excluded_404s:
- ^
buffer_size: 30