一个 pitchfork 进程承担大部分负载是正常的——只有当第一个进程繁忙时,才会选择其他进程。内存随时间增长也是正常的。尽管在缓存/Ruby JIT 等一切完成预热后,内存最终应该会达到稳定状态。
这是我们一个生产集群在 7 天周期内的图表。它跟踪的是内存使用量最高的那个进程。绿色虚线表示部署(即 pitchfork 的新启动):
因此你可以看到,在初始启动后内存确实会增长,但随后稳定在略低于 1.4GB 的水平。由于该集群正在为数百个站点提供服务,所以在具体数值方面可能不是最好的比较对象……但希望这个增长过程的可视化展示会有所帮助。
仅查看每个进程的 RSS 数值并不能反映全貌。Pitchfork 是一个“forking web server”(通过 fork 创建工作进程的 Web 服务器)。它会启动“模具”(mold)进程,然后所有工作进程都通过写时复制(copy-on-write)内存模式从该进程 fork 而来。因此,虽然 worker[0] 的 RSS 可能显示为 500mb,但其中约 200mb 是与模具进程及其他所有工作进程共享的。
在不远的将来,我们希望启用 Pitchfork 的 “reforking” 功能。它会定期终止工作进程,并从已预热的工作进程中重新 fork 它们,以便它们随时间推移尽可能多地共享内存。不过,我们需要做一些工作来确保我们的所有代码都与这种模式兼容 ![]()
