【问题标题】:Tracing memory leak in resque-scheduler process on Ruby MRI 1.9.3在 Ruby MRI 1.9.3 上跟踪 resque-scheduler 进程中的内存泄漏
【发布时间】:2014-10-18 19:08:43
【问题描述】:

我在 Ruby MRI 1.9.3(作为 Rails 3.2.13 的一部分)环境中运行 resque-scheduler,不知何故发生了内存泄漏,这让我抓狂。它不会发生在我的 MacOS 开发机器上(在完全相同相同的环境中运行),但会发生在我们在 AWS 上运行的每台 64 位 Ubuntu 12.04.4 LTS 机器上。

每次通过 resque-scheduler 主循环时,堆都会不断增长 - 尽管堆的已使用部分保持不变。此处是 GC.stat 输出的示例,GC.stat 在 GC.start 调用之后立即调用。

GC.stat: {:count=>151, :heap_used=>2424, :heap_length=>4361, :heap_increment=>1937, :heap_live_num=>840924, :heap_free_num=>145061, :heap_final_num=>0}
GC.stat: {:count=>155, :heap_used=>2428, :heap_length=>4368, :heap_increment=>1940, :heap_live_num=>840924, :heap_free_num=>146688, :heap_final_num=>0}
GC.stat: {:count=>159, :heap_used=>2432, :heap_length=>4375, :heap_increment=>1943, :heap_live_num=>840924, :heap_free_num=>148121, :heap_final_num=>0}
GC.stat: {:count=>164, :heap_used=>2437, :heap_length=>4384, :heap_increment=>1947, :heap_live_num=>840924, :heap_free_num=>150347, :heap_final_num=>0}
GC.stat: {:count=>170, :heap_used=>2443, :heap_length=>4395, :heap_increment=>1952, :heap_live_num=>840924, :heap_free_num=>152593, :heap_final_num=>0}
GC.stat: {:count=>176, :heap_used=>2449, :heap_length=>4406, :heap_increment=>1957, :heap_live_num=>840924, :heap_free_num=>155230, :heap_final_num=>0}
GC.stat: {:count=>181, :heap_used=>2454, :heap_length=>4415, :heap_increment=>1961, :heap_live_num=>840924, :heap_free_num=>157266, :heap_final_num=>0}
GC.stat: {:count=>191, :heap_used=>2464, :heap_length=>4433, :heap_increment=>1969, :heap_live_num=>840924, :heap_free_num=>161334, :heap_final_num=>0}

作为一个单独的问题,RUBY_FREE_MIN、RUBY_HEAP_MIN_SLOTS、RUBY_GC_MALLOC_LIMIT 环境变量似乎对 1.9.3 GC 的行为方式没有任何影响。随着 heap_increment 的增长,问题仅仅是因为一些硬编码设置,GC 认为它需要不断增加堆大小吗?

[编辑]

再看一遍,我可以看到 heap_used 正在上升。但是如果我考虑与 GC.stat 一起打印的 ObjectSpace.count_objects,那就没有意义了:

GC.stat: {:count=>172, :heap_used=>2438, :heap_length=>4386, :heap_increment=>1948, :heap_live_num=>841064, :heap_free_num=>150208, :heap_final_num=>0}
ObjectSpace.count_objects: {:TOTAL=>991767, :FREE=>92284, :T_OBJECT=>45577, :T_CLASS=>10048, :T_MODULE=>2452, :T_FLOAT=>1038, :T_STRING=>449766, :T_REGEXP=>4537, :T_ARRAY=>213156, :T_HASH=>17273, :T_STRUCT=>591, :T_BIGNUM=>1605, :T_FILE=>6, :T_DATA=>91099, :T_MATCH=>17, :T_COMPLEX=>1, :T_RATIONAL=>436, :T_NODE=>57652, :T_ICLASS=>4229}
GC.stat: {:count=>173, :heap_used=>2439, :heap_length=>4388, :heap_increment=>1949, :heap_live_num=>840996, :heap_free_num=>150016, :heap_final_num=>0}
ObjectSpace.count_objects: {:TOTAL=>992173, :FREE=>150621, :T_OBJECT=>45073, :T_CLASS=>9922, :T_MODULE=>2452, :T_FLOAT=>636, :T_STRING=>403784, :T_REGEXP=>4502, :T_ARRAY=>207916, :T_HASH=>15856, :T_STRUCT=>591, :T_BIGNUM=>14, :T_FILE=>6, :T_DATA=>89977, :T_MATCH=>17, :T_COMPLEX=>1, :T_RATIONAL=>63, :T_NODE=>56639, :T_ICLASS=>4103}

当所有对象计数下降时,heap_used 是如何上升的?

【问题讨论】:

    标签: ruby memory-leaks garbage-collection ruby-1.9.3


    【解决方案1】:

    在深入研究 resque_scheduler 代码后,我找到了内存泄漏的罪魁祸首。它是(鼓)“Object.methods”。可怜的 resque_scheduler 正试图在它即将入队的工作上找到一些钩子,并为此使用反射。我相信我们只在 resque_scheduler 上注意到这一点的原因是因为它是 A. 在没有分叉的情况下运行而 B. 使用 Object.methods 的唯一守护进程。

    以下代码在 irb 中运行时会泄漏大约 8Mb 的内存:

    (1..1000).each do
      Object.methods
    end
    

    一直以来,从 ruby​​ 的对象空间的角度来看,没有使用额外的内存。

    问题显然与我们正在使用的 linux 映像上的 malloc 有关。我在那里编译了最新的 ruby​​ 2.1.3,上面的例子同样会泄漏内存。然后我用 jemalloc 而不是 stock malloc 编译了最新的 1.9.3(p547),上面的例子不再泄漏。所以,我相信这是解决方案。

    如果有人能更清楚地了解他们认为这里会发生什么,那就太好了。

    【讨论】:

    • 对于基于 jemalloc 的 ruby​​,我做了: 1. 下载/配置/制作/安装 jemalloc (canonware.com/jemalloc/download.html ) 2. 导出 LD_LIBRARY_PATH=jemalloc_so_path_where_it_was_installed 3. 下载 ruby​​ 1.9.3p547 源代码,执行“配置” -ljemalloc",然后制作/安装
    • 伙计,这很容易理解,因为我也有类似的问题;一个盒子上的 Puma 内存泄漏,以及 resque 做这件事的 Rails 盒子上的内存泄漏。将近一年后,对此有何补充说明?我将 derailed_benchmarks gem 用于 Puma 泄漏,在使用生产的开发中没有泄漏,就在我添加 Puma 时。然后我有这个盒子来弄清楚并想知道使用 thie jemalloc 的 2.1.5 是否可以帮助我。想法?
    • 内存泄漏的可能原因有很多,请在服务器上的 Rails 控制台中运行 Object.methods 循环,检查是否有内存泄漏。如果是,请考虑使用不同的 MRI 版本...
    猜你喜欢
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多