当有足够的空闲堆插槽时,ruby请求更多内存

时间:2017-06-03 11:24:33

标签: ruby-on-rails ruby garbage-collection sidekiq mri

我们正在运行服务器

  • Sidekiq 4.2.9
  • rails 4.2.8
  • MRI 2.1.9

此服务器定期从外部API生成一定数量的导入,对它们执行一些计算并将这些值保存到数据库中。

大约3个星期前,服务器开始挂起,正如我从NewRelic看到的那样(当ssh'编辑它时) - 随着时间的推移消耗越来越多的内存,最终占用所有可用的RAM,然后服务器挂起。

我已经阅读了一些关于ruby GC如何工作的文章,但仍然无法理解,为什么在凌晨5点30分堆积大小从~2.3M跳到3M,当时还有可用的1M可用堆插槽(默认为GC设置)

enter image description here

类似的行为,下午3:35: enter image description here

所以,问题是:

  1. 如何让Ruby填充免费堆插槽而不是从操作系统请求新插槽?
  2. 如何让它向系统释放空闲堆插槽?

1 个答案:

答案 0 :(得分:3)

  

如何让Ruby填充空闲堆插槽而不是从OS请求新插槽?

您的图表没有“完整”的保真度。假设GC.stat是由Newrelic调用的,或者恰好恰逢其时。

很可能你的插槽耗尽,堆积增长,而且由于堆积不会缩小,所以你会遇到一堆臃肿的堆。

为了缓解一些痛苦,你可以将RUBY_GC_HEAP_GROWTH_MAX_SLOTS限制为一个理智的数字,类似100,000就可以了,我试图在核心设置一个默认设置。

另外

  • 创建运行的作业和运行时间的持久日志(持续时间等),在作业运行前后收集GC.stat

  • 按队列拆分作业,在一台服务器上运行1个队列,在另一台服务器上运行其他队列,查看哪个队列和哪个作业导致问题负责

  • 使用火焰图或其他剖析工具描述您拥有的各种工作

  • 减少您作为实验运行的并发作业数量,或在某些作业类型之间放置互斥锁。一次1个“工作a”可能是好的,并且20个并发“工作a”一次可能会膨胀记忆。