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

查看:99
本文介绍了如何在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?

宝石

  • rails 3.2.16
  • event_bus 1.0.0 (https://github.com/kevinrutherford/event_bus)
  • activerecord-fast-import (https://github.com/jsuchal/activerecord-fast-import)

耙任务

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

我尝试过这些模式

  • RubyProf :: ALLOCATIONS
  • RubyProf :: MEMORY

文档中所说的是:

RubyProf :: ALLOCATIONS 对象分配报告显示程序中每个方法分配多少个对象.

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-Mass

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

使用

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).红宝石2.2之前的符号. 0 没有被垃圾回收,因此请确保您的CSV或部分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天全站免登陆