31

質問

rake タスクでメモリ リークをデバッグしています。次の呼び出し履歴を確認したい:

  • 生き物
  • それらのオブジェクトを最初に割り当てたオブジェクトまたはライン

これは ruby​​-prof で可能ですか?

そうでない場合、どのツールを使用すればよいですか?

設定

宝石

レーキタスク

  • DATA LOAD INFILE および Active Record オブジェクトを使用して、CSV ファイルを MySql データベースに直接インポートします。

私が試したこと

モードを試してみた

  • RubyProf::割り当て
  • RubyProf::メモリ

ドキュメントに記載されているのは次のとおりです。

RubyProf::ALLOCATIONS オブジェクト割り当てレポートは、プログラム内の各メソッドが割り当てるオブジェクトの数を示します。

RubyProf::MEMORY メモリ使用量レポートは、プログラム内の各メソッドが使用するメモリ量を示します。

これは、ruby-prof が生きているオブジェクトだけでなく、オブジェクトの総割り当てを報告するだけであることを意味します。

Ruby-MassBloat Checkを試しましたが、どちらもやりたいことができないようです。Ruby-Mass も何らかの理由でメモリ内の FactoryGirl オブジェクトを見つけてクラッシュします...

4

4 に答える 4

38

パッチを適用した 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

prypry-byebugを使用してメモリ ヒープの探索を開始し、おそらくメモリ ヒープが大きくなると思われる場所からコード内の異なるセグメントをそれぞれ試します。Ruby 2.1 より前は、あるオブジェクト タイプが特に大きくなるかどうかを確認するために、常に結果の違いに依存しObjectSpace.count_objectsて計算していました。

増加し続けるオブジェクトの数が、増加し続けるのではなく、反復中にはるかに少ない量に再テストされると、ガベージ コレクションは適切に機能します。いずれにせよ、ガベージ コレクターは常に実行されている必要があります。ガベージ コレクターの統計情報を調べることで安心できます。

私の経験から、これは String または Symbol ( T_STRING) のいずれかです。Ruby 2.2.0 より前のシンボルはガベージ コレクションされていないため、CSV またはその一部が途中でシンボルに変換されないようにしてください。

不安がある場合は、JRuby を使用して JVM でコードを実行してみてください。少なくとも、メモリ プロファイリングは、VisualVM などのツールでより適切にサポートされます。

于 2014-01-06T18:43:14.210 に答える
5

時間を節約するために、最初にメモリ リークのある Ruby gem のリストを確認できます。https://github.com/ASoftCo/leaky-gems

于 2015-10-23T16:13:28.223 に答える
5

Ruby 2.1 で使用するための memory_profiler gemを検討してください。

于 2014-11-10T15:41:27.317 に答える