如何追踪 Ruby 代码中的内存泄漏? [英] How do I track down a memory leak in my Ruby code?

查看:22
本文介绍了如何追踪 Ruby 代码中的内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在调试 rake 任务中的内存泄漏.我想查看以下调用堆栈:

I'm debugging a memory leak in a rake task. I want to see a call stack of:

  • 有生命的物体
  • 最初分配这些对象的是什么对象或行

这可以用 ruby​​-prof 实现吗?

Is this possible with ruby-prof?

如果没有,我应该使用什么工具?

If not, what tool should I use?

宝石

耙任务

  • 使用 DATA LOAD INFILE 和 Active Record 对象将 CSV 文件直接导入 MySql 数据库.

我已经尝试过这些模式

  • RubyProf::分配
  • RubyProf::MEMORY

文档中的所有内容是:

RubyProf::分配对象分配报告显示程序中每个方法分配的对象数量.

RubyProf::ALLOCATIONS Object allocation reports show how many objects each method in a program allocates.

RubyProf::MEMORY内存使用情况报告显示程序中每种方法使用的内存量.

RubyProf::MEMORY Memory usage reports show how much memory each method in a program uses.

这意味着 ruby​​-prof 只报告对象的总分配,而不仅仅是存活的对象.

This implies that ruby-prof just reports on the total allocation of objects, not just the ones that are living.

我试过 Ruby-MassBloat Check 但似乎都不能做我想做的事.Ruby-Mass 也会崩溃,因为它出于某种原因在内存中查找 FactoryGirl 对象...

I've tried Ruby-Mass and Bloat Check but neither seem to be able to do what I want. Ruby-Mass also crashes because it's finding FactoryGirl objects in memory for some reason...

推荐答案

我没有发现 ruby​​-prof 在定位内存泄漏方面很有用,因为您需要一个打过补丁的 Ruby 解释器.在 Ruby 2.1 中跟踪对象分配变得更加容易.或许自己探索一下才是最好的选择.

I did not find ruby-prof very useful when it came to locating memory leaks, because you need a patched Ruby interpreter. Tracking object allocation has become easier in Ruby 2.1. Maybe it is the best choice to explore this yourself.

我推荐 tmml 的博文 Ruby 2.1: objspace.so,他是Ruby 核心开发人员.基本上,您可以在调试应用程序时获取大量信息:

I recommend the blog post Ruby 2.1: objspace.so by tmml who is one of the Ruby core developers. Basically you can fetch a lot of information while debugging your application:

ObjectSpace.each_object{ |o| ... }
ObjectSpace.count_objects #=> {:TOTAL=>55298, :FREE=>10289, :T_OBJECT=>3371, ...}

require 'objspace'
ObjectSpace.memsize_of(o) #=> 0 /* additional bytes allocated by object */
ObjectSpace.count_tdata_objects #=> {Encoding=>100, Time=>87, RubyVM::Env=>17, ...}
ObjectSpace.count_nodes #=> {:NODE_SCOPE=>2, :NODE_BLOCK=>688, :NODE_IF=>9, ...}
ObjectSpace.reachable_objects_from(o) #=> [referenced, objects, ...]
ObjectSpace.reachable_objects_from_root #=> {"symbols"=>..., "global_tbl"=>...} /* in 2.1 */

使用 Ruby 2.1,您甚至可以开始跟踪新对象的分配并收集有关每个新对象的元数据:

With Ruby 2.1 you can even start to track allocation of new objects and gather metadata about every new object:

require 'objspace'
ObjectSpace.trace_object_allocations_start

class MyApp
  def perform
    "foobar"
  end
end

o = MyApp.new.perform
ObjectSpace.allocation_sourcefile(o) #=> "example.rb"
ObjectSpace.allocation_sourceline(o) #=> 6
ObjectSpace.allocation_generation(o) #=> 1
ObjectSpace.allocation_class_path(o) #=> "MyApp"
ObjectSpace.allocation_method_id(o)  #=> :perform

使用 prypry-byebug 并开始探索您认为它可能会增长的内存堆,分别尝试代码中的不同段.在 Ruby 2.1 之前,我总是依靠 ObjectSpace.count_objects 并计算结果的差异,看看一种对象类型是否特别增长.

Use pry and pry-byebug and start exploring the memory heap where you think it will probably grow, respectively try different segments in your code. Before Ruby 2.1 I always relied on ObjectSpace.count_objects and calculated the result's difference, to see if one object type grows in particularly.

当不断增长的对象数量在迭代过程中重新测试回小得多而不是不断增长时,垃圾收集工作正常.无论如何,垃圾收集器应该一直运行,您可以通过查看 垃圾收集器统计信息.

The garbage collection works properly when the number of objects growing are retested back to a much smaller amount during the iterations as opposed to keep growing. The garbage collector should run all the time anyway, you can reassure yourself by looking into the Garbage Collector statistics.

根据我的经验,这是字符串或符号 (T_STRING).符号 之前 ruby​​ 2.2.0 不是垃圾收集,因此请确保您的 CSV 或其中的一部分不会在途中转换为符号.

From my experience this is either String or Symbol (T_STRING). Symbols before ruby 2.2.0 were not garbage collected so make sure your CSV or parts of it is not converted into symbols on the way.

如果您觉得不舒服,请尝试使用 JRuby 在 JVM 上运行您的代码.至少,VisualVM 等工具可以更好地支持内存分析.

If you do not feel comfortable, try to run your code on the JVM with JRuby. At least the memory profiling is a lot better supported with tools like VisualVM.

这篇关于如何追踪 Ruby 代码中的内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆