我有大约六个 Sidekiq worker 执行JSON 爬取。根据端点的数据集大小,它们需要1分钟到4小时完成。尤其是那个需要4小时的长时间任务,我发现内存会随着时间的推移略微增加。
这不是问题,直到我想再次调度同样的 worker 任务时。内存没有被释放并且堆积,直到我遇到 Linux OOM Killer,它会摆脱我的 Sidekiq 进程。
内存泄漏? 我查看了 ObjectSpace 中不同对象的数量:
ObjectSpace.each_object.inject(Hash.new(0)) { |count, o| count[o.class] += 1 }
实际上并没有增加,哈希、数组等集合保持不变,短暂的增加会被垃圾回收器清除掉,gc.stat[:count]
告诉我,垃圾回收器也在工作。
即使工作线程结束,例如我得到了打印的[完成]且没有工作线程了,内存仍然没有被释放。造成这种情况的原因是什么?我能做些什么来解决吗?编写一个终结器吗?
唯一的目前的解决方案:重启 Sidekiq 进程。
我使用Yajl进行 JSON 解析,它是一个 C 绑定。我需要它,因为它似乎是唯一一个适当实现流式读写的快速 JSON 解析器。