Ruby on rails 如何追踪Ruby代码中的内存泄漏? 问题

Ruby on rails 如何追踪Ruby代码中的内存泄漏? 问题,ruby-on-rails,ruby,memory,memory-leaks,ruby-prof,Ruby On Rails,Ruby,Memory,Memory Leaks,Ruby Prof,我正在调试rake任务中的内存泄漏。我想查看以下调用堆栈: 活体 最初分配这些对象的对象或行是什么 ruby教授有可能做到这一点吗 如果没有,我应该使用什么工具 安装程序 宝石 轨道3.2.16 事件总线1.0.0() activerecord快速导入() Rake任务 使用数据加载填充和活动记录对象将CSV文件直接导入MySql数据库 我试过的 我已经试过了 RubyProf::分配 RubyProf::内存 文件中所述内容如下: RubyProf::分配 对象分配报告显示程序

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

  • 活体
  • 最初分配这些对象的对象或行是什么
ruby教授有可能做到这一点吗

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

安装程序 宝石

  • 轨道3.2.16
  • 事件总线1.0.0()
  • activerecord快速导入()
Rake任务

  • 使用数据加载填充和活动记录对象将CSV文件直接导入MySql数据库
我试过的 我已经试过了

  • RubyProf::分配
  • RubyProf::内存
文件中所述内容如下:

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

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

这意味着ruby prof只报告对象的总分配情况,而不仅仅是活的对象


我试过了,但两人似乎都做不到我想要的。Ruby Mass也会崩溃,因为出于某种原因,它在内存中查找FactoryGirl对象…

我发现Ruby prof在查找内存泄漏时不是很有用,因为您需要一个修补过的Ruby解释器。在Ruby 2.1中,跟踪对象分配变得更加容易。也许这是你自己探索的最佳选择

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

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,您甚至可以开始跟踪新对象的分配,并收集每个新对象的元数据:

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
使用和开始探索您认为可能会增长的内存堆,分别尝试代码中的不同段。在Ruby 2.1之前,我一直依赖于
ObjectSpace.count_objects
并计算结果的差异,以查看是否有一种对象类型会特别增长

当在迭代过程中重新测试增长的对象数量,使其返回到更小的数量,而不是保持增长时,垃圾收集工作正常。无论如何,垃圾收集器应该一直运行,您可以通过查看

根据我的经验,这是字符串或符号(
T\u String
)。符号未被垃圾收集,因此请确保您的CSV或其部分不会在途中转换为符号

如果您觉得不舒服,请尝试使用JRuby在JVM上运行代码。至少像VisualVM这样的工具更好地支持内存评测。

有一个gem,它在ObjectSpace上提供了一个很好的api

解决此问题的方法之一是在处理完对象后检查引用

object = ...
# more logic
puts Mass.references(object)
如果至少有一个引用,则对象不会被垃圾收集,您需要弄清楚如何删除该引用。例如:

object.instance_variable_set("@example", nil)

# or

ObjectSpace.each_object(Your::Object::Class::Name).each do |obj|
  obj.instance_variable_set("@example", nil)
end

考虑与Ruby 2.1一起使用。

为了节省时间,您可以先查看内存泄漏的Ruby Gem列表

第一个问题:您是否使用任何已知泄漏问题的gems,如ImageMagick/RMagick?我在rake任务中使用EventBus和activerecord快速导入。我也在运行Rails 3.2.16。我已经安装了很多其他gem,但我在rake任务中没有安装。您可以随时尝试偶尔调用
GC.start
,看看这是否会释放一些内存。它使你的应用程序速度变慢,但内存占用通常要低得多。@tadman我已经做了很多了-它减少了一点点内存,但它似乎仍然在某个地方保留了很多…仅供参考,我也在博客上写过这一点,直到:符号不是垃圾收集的符号是GC开始的