読者です 読者をやめる 読者になる 読者になる

ObjectSpace.reachable_objects_from()の活用 - GC Advent Calendar

Garbage Collection Advent Calendarの2日目の記事です。

Ruby2.0.0の目玉機能である ObjectSpace.reachable_objects_from の活用法を書いてみましょう。
ドキュメントはソースコードのRDocを
ruby/objspace.c at 020cc0ad5c5b4b2b2aac9e0a7fc9d35cfc76dfdc · ruby/ruby · GitHub

とあるオブジェクトがメモリリークしているとわかった時、どこから参照されているか調べたいわけです。その参照を切ればちゃんとGCされるはずですので。

ということで、以下のようにObjectSpace.each_objectを併用して調べてみます。

require 'objspace'

def foo
  @bar = ["I am bar"]
  @baz = ["I am baz"]
  leak_obj = "I am leaky..(T_T)"

  @bar << leak_obj
  @baz << leak_obj
  return leak_obj.object_id
end

leak_id = foo
@baz.pop

ObjectSpace.each_object do |o|
  if ObjectSpace.reachable_objects_from(o).map(&:object_id).include?(leak_id)
    p [o.object_id, o]
  end
end
% ruby /tmp/d.rb
[15782480, ["I am bar", "I am leaky..(T_T)"]]

@barから参照を外せばGCされることがわかりましたね。便利。