7

次のパターンのアプリケーションがあります。

  • アイドル時間の後に休止状態になる 2 つの実行時間の長いプロセスと、メモリ消費量が予想どおりに減少する
  • N (0 < N < 100) 個のワーカー プロセスが何らかの作業を行い、アイドル状態が 10 秒以上続くと休止状態になり、アイドル状態が 2 時間以上続くと終了する
  • 夜間、アクティビティがない場合、プロセス メモリはアプリケーションの開始時とほぼ同じ値に戻ります。これは、すべてのワーカーが停止しているためと予想されます。

問題は、「システム」セクションが増え続けることです (約 1GB/週)。

私の質問は、そこに保存されているもの、またはその領域にメモリを割り当てて解放していない人をデバッグするにはどうすればよいかということです。

私はすでにlists:keysearch/3をテストしましたが、それは私が使用している唯一のネイティブのものであるため、メモリリークはないようです(ポートなし、ドライバーなし、NIFなし、BIFなし、何もありません)。Erlang のバージョンは R15B03 です。

現在のerlang:memory()の出力は次のとおりです (トラフィックはわずかで、アプリは 2 月 3 日に開始されました)。

[{total,378865650},
{processes,100727351},
{processes_used,100489511},
{system,278138299},
{atom,1123505},
{atom_used,1106100},
{binary,4493504},
{code,7960564},
{ets,489944},
{maximum,402598426}]

これは 64 ビット システムです。ご覧のとおり、「システム」セクションは約 270MB で、「プロセス」セクションは約 100MB です (夜間は約 16MB まで低下します)。

4

1 に答える 1

4

問題が見つかったようです。

プロセスが定期的なGCまたはkillをサブスクライブできる「process_killer」gen_serverがあります。サブスクライブ関数は、一部のプロセスによって受信された各メッセージで呼び出され、GC/kill (リアームのようなもの) を延期します。

このプロセスは、まだ監視されていない場合は erlang:monitor を実行して、デッド プロセスをキャッチし、ウォッチ リストから削除します。処理された各メッセージの再購読行にコメントすると、「システム」領域は正常に動作するようです。これは、私の process_killer のバグであり、モニター参照をリークすることを意味します (erlang:monitor を複数回呼び出すことができ、呼び出しごとに参照が作成されることを思い出してください)。

私がこのアイデアにたどり着いたのは、ループで erlang:monitor を呼び出していた単純なモジュールをテストし、各呼び出しで最大 13 バイトの「システム」領域が拡大するのを見たからです。

労働者自身はモニターを持って死ぬので大丈夫でした。受信メッセージごとに GC リアームを呼び出していたワーカーにすべてのメッセージをディスパッチする、長時間実行される (アプリで開始し、アプリで停止する) プロセスが 1 つあります。時間であり、リリースされることはありません。

今後の参考のために、この回答をここに書いています。

TL;DR; 長時間実行されているプロセスでモニター参照をリークしていないことを確認してください。

于 2013-02-09T13:10:18.730 に答える