JSONクロールを実行する6人のSidekiqワーカーがいます。エンドポイントのデータセットサイズに応じて、1分から4時間で終了します。特に、4時間かかる長いものを見ると、時間の経過とともにわずかなメモリの増加が見られます。
同じワーカージョブを再度スケジュールするまでは、問題ありません。 Sidekiqプロセスを削除するLinuxOOM Killerに遭遇するまで、メモリは割り当て解除されずにスタックします。
メモリリーク? ObjectSpace内のさまざまなオブジェクトの数を確認しました。
ObjectSpace.each_object.inject(Hash.new(0)) { |count, o| count[o.class] += 1 }
そこには実際には増加はなく、ハッシュ、配列などのセットは同じままで、短い増加はガベージコレクターによって一掃され、gc.stat[:count]
はガベージコレクターも機能していることを教えてくれます。
労働者が終了した後でも、例えば[Done]がログに記録され、ビジー状態のワーカーはなくなり、メモリの割り当てが解除されません。その理由は何ですか?これに対して何かできますか?ファイナライザーを書きますか?
唯一の現在の解決策:Sidekiqプロセスを再起動します。
私はRuby 2.0.0で、Ruby MRIを使用しています。
JSONの解析には、 Yajl を使用するため、Cバインディングを使用します。ストリーミングされた読み取りと書き込みを適切に実装する唯一の高速JSONパーサーのように見えるので、私はそれが必要です。
Sidekiqを書いたMike Perhamは、ここでこれに対処しました: http://www.mikeperham.com/2009/05/25/memory-hungry -ルビーデーモン/
tl; dr version:MRIはメモリを返しません。できることは、ヒープを制御することです。これを行うには、 Ruby Enterprise Edition が提案されました。
これが役立つかどうかはわかりませんが、それが状況です-馬の口から直接。