【问题标题】:Ruby code memory leak in loop循环中的 Ruby 代码内存泄漏
【发布时间】:2016-10-23 21:45:58
【问题描述】:

以下代码存在内存泄漏。它在 ruby​​ 2.1.1 下运行。我无法找到实际的泄漏。

q = Queue.new("test")
while true do
  m = q.dequeue
  body = JSON.parse(m.body)
  user_id = body["Records"][0]
  user = V2::User.find(user_id)
  post = V2::Post.find(post_id)  
end

运行几个小时后,我添加了 GC.start,但它并没有解决问题

q = Queue.new("test")
while true do
  m = q.dequeue
  body = JSON.parse(m.body)
  user_id = body["Records"][0]
  user = V2::User.find(user_id)
  post = V2::Post.find(post_id) 
  GC.start 
end

我不知道如何找到实际的内存泄漏。

【问题讨论】:

  • Queue 是如何定义的? Queue#dequeue 是什么样的(我注意到 dequeue 没有为 Ruby 附带的 Queue 定义)?谁将对象排入队列?队列中平均有多少对象?
  • 您的问题得到解答了吗?

标签: ruby-on-rails ruby ruby-2.1


【解决方案1】:

尝试从下往上删除这些行,并查看内存泄漏是否仍然存在。内存泄漏可能来自 find 方法,也可能来自 JSON.parse(极不可能)或自定义 Queue 数据结构。如果删除所有行后内存泄漏仍然存在,则很可能来自工作人员本身和/或运行工作人员的程序。

q = Queue.new("test")
while true do
  m = q.dequeue # Finally remove this and stub the while true with a sleep or something
  body = JSON.parse(m.body) # Then remove these two lines
  user_id = body["Records"][0]
  user = V2::User.find(user_id) # Remove the bottom two lines first
  post = V2::Post.find(post_id)
end

【讨论】:

  • 乍一看,我也是这么想的。这个循环肯定会导致 CPU 使用率很高,但为什么会导致内存使用率很高呢?
  • @Dbz 实际上是一个工人。它将每秒钟运行一次。它将列在队列中。如果有任何消息被推送到队列,它将从队列中获取消息并完成工作。
  • 是的。你们绝对是对的。我已经用调试技巧更新了我的答案。请务必在尝试后发布结果。
  • @SaravanaKumAr 这个由“可能”和“可能”组成的答案究竟是如何被批准为正确的?你检查过这个假设吗?你声称泄漏需要几个小时才能注意到?请避免标记未被证明对您有效的答案
  • @mudasobwa 我认为您链接到了一个出色且内容丰富的堆栈溢出答案。他的问题表明他不知道如何找到内存泄漏。如果我的回答(包括“可能”和“可能”)能够帮助他找到内存泄漏,并且对他有用,那么投票和/或标记为已接受似乎并非不合理.话虽如此,您对为什么和他能做什么的回答同样重要。
【解决方案2】:

我敢打赌,问题在于引入的局部变量(原文如此!)。摆脱user_idpost_id,它可能会停止泄漏:

# user_id = body["Records"][0]
# user = V2::User.find(user_id)
user = V2::User.find(body["Records"][0]) # sic!

原因是Ruby如何stores objects in RValues

【讨论】:

  • 每次 GC.start 后局部变量内存会被释放吗?
  • 例如正在运行一个循环 1000 次。每次在该循环内,我只是分配 user_id = some_value。每个循环也在运行 GC.start 。在那种情况下,什么时候内存会被释放?你对此有何看法。而 i
  • 我已经链接了一个详细的描述,请你阅读两遍。 GC 不释放堆。让我再重复一遍:GC 不释放堆。不管你运行多少次,GC 不释放堆。因此,在循环的每次后续迭代中,显然适合 40 字节的每个 user_id 将分配一个 不会释放回操作系统的新堆。
  • 我明白你的回答。我要问的是该堆何时会释放回操作系统?
  • 从不。 请阅读我链接的答案,其中包含详细说明。
猜你喜欢
  • 2014-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-08
  • 2016-01-13
  • 2018-05-13
  • 2014-12-28
相关资源
最近更新 更多