隐式vs显式垃圾收集

时间:2018-05-07 08:48:06

标签: ruby-on-rails ruby memory-management garbage-collection profiling

背景

我创建了一个API,并对内存使用情况进行了分析。使用this guidememory profiler gem的每个网络服务的处理时间。

我创建了一个表来保存所有分析结果:

      Request      | Memory Usage(b) | Retained Memory(b) | Runtime(seconds)
----------------------------------------------------------------------------
  Post Login       | 444318          |   35649            | 1.254
  Post Register    | 232071          |   32673            | 0.611
  Get 10 Users     | 11947286        |   2670333          | 3.456
  Get User By ID   | 834953          |   131300           | 0.834

注意:所有数字都是连续3次呼叫同一服务的平均数。

我读了很多指南和答案(比如thisthis)说垃圾收集器负责释放内存,我们不应该明确地干涉内存管理。

然后我通过在APIController中添加以下过滤器强制垃圾收集器在每个操作之后启动(用于测试目的):

after_action :dispose

def dispose
   GC.start
end

我发现内存使用量减少了太多(超过70%),之前保留的内存几乎相同,运行时间也减少了。

      Request      | Memory Usage(b) | Retained Memory(b) | Runtime(seconds)
----------------------------------------------------------------------------
  Post Login       | 38636           |   34628            | 1.023
  Post Register    | 37746           |   31522            | 0.583
  Get 10 Users     | 2673040         |   2669032          | 2.254
  Get User By ID   | 132281          |   128913           | 0.782

问题:

  1. 添加此类过滤器是一种好习惯,副作用是什么?
  2. 我认为运行时间比以前更多,但似乎更少,可能是什么原因?
  3. 更新

    我正在使用Ruby 2.3.0并且我使用gc_tracer gem来监控堆状态,因为我害怕old garbage collection issues highlighted in Ruby 2.0 & 2.1

      

    问题是Ruby GC是在对象总数上触发的,   而不是已用内存的总量

    然后进行压力测试,我运行以下内容:

    while true
      "a" * (1024 ** 2)
    end
    

    结果是内存使用量不超过以下限制(it was exceeding before and GC wont be triggered):

    RUBY_GC_MALLOC_LIMIT_MAX
    RUBY_GC_OLDMALLOC_LIMIT_MAX
    

    所以现在我很确定同样的GC问题是2.0& 2.1在2.3中不再存在,但通过添加上述过滤器(after_action :dispose)仍然得到以下积极结果:

    • 堆内存增强了5%到10%(check this related question
    • 一般执行时间增加20%至40%(使用第三方工具 Postman 进行测试,消耗我的API)

    我仍然在寻找上述两个问题的答案。

    非常感谢任何反馈

0 个答案:

没有答案