问题
我正在调试 rake 任务中的内存泄漏。我想查看以下调用堆栈:
- 活物
- 最初分配给这些对象的是什么对象或行
ruby-prof 可以做到这一点吗?
如果不是,我应该使用什么工具?
设置
gem
- 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)
rake 任务
- 使用 DATA LOAD INFILE 和 Active Record 对象将 CSV 文件直接导入 MySql 数据库。
我的尝试
我已经尝试过这些模式
- RubyProf::ALLOCATIONS
- RubyProf::MEMORY
文档中说的是:
RubyProf::ALLOCATIONS 对象分配报告显示程序中每个方法分配了多少对象。
RubyProf::MEMORY 内存使用报告显示程序中每个方法使用了多少内存。
这意味着 ruby-prof 只报告对象的总分配,而不仅仅是那些正在存活的对象。
我试过 Ruby-Mass和 Bloat Check但似乎都无法做我想做的事。 Ruby-Mass 也因为某种原因在内存中查找 FactoryGirl 对象而崩溃...
最佳答案
我没有发现 ruby-prof 在定位内存泄漏方面很有用,因为您需要一个修补过的 Ruby 解释器。在 Ruby 2.1 中跟踪对象分配变得更加容易。也许这是自己探索的最佳选择。
我推荐博文Ruby 2.1: objspace.so作者 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
使用 pry和 pry-byebug并开始探索您认为可能会增长的内存堆,分别尝试代码中的不同段。在 Ruby 2.1 之前,我总是依靠 ObjectSpace.count_objects
计算结果的差异,看看是否有一个对象类型特别增长。
当不断增长的对象数量在迭代过程中被重新测试到一个小得多的数量时,垃圾收集可以正常工作,而不是继续增长。无论如何,垃圾收集器应该一直运行,您可以通过查看 Garbage Collector statistics. 来让自己放心。
根据我的经验,这是字符串或符号 (T_STRING
)。符号 before ruby 2.2.0没有被垃圾收集,因此请确保您的 CSV 或其部分未在途中转换为符号。
如果您觉得不舒服,请尝试使用 JRuby 在 JVM 上运行您的代码。至少,VisualVM 等工具更好地支持内存分析。
关于ruby-on-rails - 如何追踪我的 Ruby 代码中的内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20956401/