2

[処方箋: ここに書かれていることが Delayed::Job に固有のものではないことはわかっています。しかし、それは文脈を確立するのに役立ちます.]

アップデート

SQL クエリがガベージ コレクションされていないと思います。私のアプリケーションは、多数の大きな SQL 挿入/更新操作 (それぞれ 160K バイト、1 秒あたり約 1 回) を生成し、次の方法で PostgreSQL に送信します。

ActiveRecord::Base.connection.execute(my_large_query)

これらのデータベース操作を実行すると、アプリケーションは際限なくゆっくりと成長します。データベース操作をスタブ化すると (ただし、アプリで他のすべての機能を実行すると)、肥大化は停止します。

だから:なぜこれが起こっているのか、どうやってそれを特定できるのか、どうすればそれを止めることができるのかについてのアイデアはありますか?

元の質問

Web からデータを盗み出し、PostgreSQL データベースにレコードを作成するタスクを遅らせました。それらは正常に動作しているように見えますが、vmemsize=100M から開始し、10 分以内に vmemsize=500M にバルクアップし、成長を続けています。VM が不足すると、8G の RAM を搭載した MacBook Pro がスラッシングを開始します。

メモリの移動先を見つけるにはどうすればよいですか?

このトピックに関する他のSOの投稿を紹介する前に:

#after(job) メソッドに以下を追加しました。

def after(job)
  clss = [Object, String, Array, Hash, ActiveRecord::Base, ActiveRecord::Relation]
  clss.each {|cls| object_report(cls, " pre-gc")}
  ObjectSpace.each_object(ActiveRecord::Relation).each(&:reset)
  GC.start
  clss.each {|cls| object_report(cls, "post-gc")}
end

def object_report(cls, msg)
  log(sprintf("%s: %9d %s", msg, ObjectSpace.each_object(cls).count, cls))
end

基本クラスの使用状況を報告し、ActiveRecord::Relation オブジェクトを明示的にリセットし (この SO 投稿で提案)、明示的に GC を実行し (この SO 投稿で提案)、オブジェクト / 文字列 / 配列 / ハッシュなどの数を報告します。あります(このSO投稿で示唆されているように)。価値があるのは、これらのクラスのどれも大幅に成長していないということです。(私が見るべき他のクラスはありますか?しかし、とにかくそれはオブジェクトの数に反映されませんか?)

Ruby 1.9 を実行しているため、memprofを使用できません。

また、Linux で実行している場合に検討したいツールは他にもありますが、私は OS X を使用しています。

4

1 に答える 1

1

アップデート

これはすべて赤ニシンだったのではないかと思います。十分に長く実行したままにすると、各ルビージョブは約1.2GBのvmsizeに成長し(ええ、それは大きいですが、今日の基準では大きくはありません)、その後850MBに縮小し、その後、これら2つの値は、大きくなり続けることなく。

私の本当の問題は、8GBのRAMを搭載したマシンで4つ以上のそのようなプロセスを実行しようとしていたことでした。これにより、使用可能なすべてのRAMがいっぱいになり、低酸素状態になりました。4つのプロセスのみを実行すると、使用可能なメモリがほぼいっぱいになるため、システムはスワッピングを開始しません。

アップデート2

いいえ、まだ問題です。ジョブを十分に長く実行させませんでした。ジョブは(ゆっくりではありますが)継続的に成長します。2つの外部ジョブを実行するだけでも、最終的にすべてのVMが消費され、私のマシンはスラッシングを開始します。

実稼働モードで実行してみましたが(開発モードでは解放されないものがキャッシュされる可能性があると考えています)、それほど大きな違いはありませんでした。

于 2012-07-12T22:26:06.873 に答える