パッチを適用した Ruby インタープリターが必要なため、メモリ リークの場所を特定することに関しては、ruby-prof はあまり役に立ちませんでした。Ruby 2.1 では、オブジェクト割り当ての追跡がより簡単になりました。たぶん、これを自分で調べるのが最良の選択です。
Ruby コア開発者の 1 人である tmml によるブログ投稿Ruby 2.1: objspace.soをお勧めします。基本的に、アプリケーションのデバッグ中に多くの情報を取得できます。
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
て計算していました。
増加し続けるオブジェクトの数が、増加し続けるのではなく、反復中にはるかに少ない量に再テストされると、ガベージ コレクションは適切に機能します。いずれにせよ、ガベージ コレクターは常に実行されている必要があります。ガベージ コレクターの統計情報を調べることで安心できます。
私の経験から、これは String または Symbol ( T_STRING
) のいずれかです。Ruby 2.2.0 より前のシンボルはガベージ コレクションされていないため、CSV またはその一部が途中でシンボルに変換されないようにしてください。
不安がある場合は、JRuby を使用して JVM でコードを実行してみてください。少なくとも、メモリ プロファイリングは、VisualVM などのツールでより適切にサポートされます。