0

私たちの目的は大きなシステムです。私たちが知っているように、今ではメモリリークが発生しているはずです。しかし、その理由を見つけるのはとても難しいです。プロセスが使用するメモリがギガバイトに達するたびに、その応答は非常に遅くなります。「上」から見たCPU使用率は常に100%で、プロセスに何もする必要がありません。

objgraph と meliae を使用してこの問題をデバッグしましたが、疑わしいものは何もありません。しかし、1 つの奇妙な問題が見つかりました。gc.get_objects() によって取得されるオブジェクトの合計サイズは、"top" から見たメモリ使用量と等しくありません。たとえば、50M ですが、"top" からは 150M です。

誰か私たちに方向性を教えてもらえますか? ありがとう。

4

1 に答える 1

6

次のようなものでオブジェクトのサイズを取得していると思います:

sum(sys.getsizeof(i) for i in gc.get_objects())

の結果にgc.get_objects()は、インタープリター自体によって消費されたメモリは含まれず、ガベージ コレクターによって追跡された Python オブジェクトのみが含まれることに注意してください。また、この関数は、メソッドから正確な結果を返すオブジェクトに依存している__sizeof__()ため、サードパーティのモジュールを使用している場合、必ずしも正確な結果が期待できるとは限りません。

すでにこれを行っているかもしれませんが、アプリケーションで定期的に呼び出して、コレクターが解放できなかった到達不能オブジェクトがあるかどうかをgc.collect()確認することができます。gc.garbageこれは、オーバーライドした循環参照を持つクラスがある場合に当てはまります__del__()( gc の Python ドキュメントを参照してください)。

コードの先頭にこの呼び出しを追加することもお勧めします。

gc.set_debug(gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS)

stderrこれにより、オブジェクトが循環参照などで見つかるたびにメッセージが出力されます。これにより、どこをより詳しく調べるかについての有用な情報が得られる場合があります。

これまでのところ、この種の問題は objgraph によって検出された可能性がありますが、長期実行デーモンでそれらをアクティブなままにして、そのような問題が発生したときの記録を取得できるため、いずれにしてもそれらを配置する価値があるかもしれません。

C 拡張機能を使用している場合 (自分で作成したものでも、サード パーティ製のものでも)、参照カウントの処理でエラーがないかコードを注意深くチェックしてください。間違いを犯すのはかなり簡単です。また、拡張機能が Python のアロケータの外部に独自のメモリを割り当てるのを止めるものは何もないことに注意してください。この場合、Python インタープリタ内で何をしても、これらのリークが検出されません。

とはいえ、メモリ使用量がまだ単調に増加していて、原因である Python オブジェクトが見つからない場合は、おそらく低レベルの C コードまたは Python インタープリター自体のリークをチェックする時期です。これは優れたツールです。これはValgrindです。

Python で Valgrind を使用するには、Python 抑制ファイルを使用する必要があります。/usr/lib/valgrind/python.suppこれは既にインストールされている場合があります。たとえば、Ubuntu は、このファイルの変更された形式を に配置します。

これを適切に行うには、Python ディストリビューションのREADME.valgrindファイルに記載されているように Python を再コンパイルする必要がありますが、これを行わなくても興味深い結果が得られる場合があります。

Valgrind で Python を実行することについては、このスタック オーバーフローの質問でさらに議論されています。

于 2013-01-08T12:29:59.190 に答える