4

数千の大きなファイル(サイズが10MBから100MBの間)を圧縮するCプログラムをSuse Linux Enterpriseで実行すると、プログラムの実行に伴ってプログラムがどんどん遅くなります(Intel Sandy Bridgeボードで32スレッドのマルチスレッドで実行されています)。 )。プログラムが完了し、再度実行されても、まだ非常に遅いです。

プログラムの実行を見ると、プログラムの実行中にメモリが使い果たされていることがわかります。これは、古典的なメモリリークの問題であると思われます。ただし、通常のmalloc()/ free()の不一致では、プログラムの終了時にすべてのメモリが返されると思います。ただし、プログラムの完了時にほとんどのメモリは再利用されません。freeまたはtopコマンドは、Mem:合計63996M、使用済み63724M、プログラムの速度が低下して停止した場合は272Mの空きを示しますが、終了後、空きメモリは約3660Mにしか戻りません。プログラムを再実行すると、空きメモリがすぐに使い果たされます。

一番上のプログラムは、実行中にプログラムがメモリの最大4%程度を使用していることを示しているだけです。

これはメモリの断片化の問題かもしれないと思いましたが、プログラム内のすべてのメモリ割り当てアクティビティをシミュレートする小さなテストプログラムを作成しました(多くのランダム化された側面が組み込まれています-サイズ/数量)。完了。だから、それだけではないと思います。

質問:

  1. プロセスが完了した後でも、メモリを永久に失うmalloc()/ free()の不一致が存在する可能性はありますか?

  2. Cプログラム(C ++ではない)の他にどのようなことが永続的なメモリ損失を引き起こす可能性がありますか?つまり、プログラムが完了し、ターミナルウィンドウが閉じた後ですか?再起動するだけでメモリが元に戻ります。ファイルが閉じられずに問題が発生するという他の投稿を読んだことがありますが、その問題はないと思います。

  3. 記憶の統計を上から見て自由にすることは有効ですか?つまり、記憶の状況を正確に説明していますか?それらはプログラムの遅さに対応しているようです。

  4. プログラムが4%のメモリ使用量しか示さない場合、valgrindのようなものがこの問題を見つけますか?

4

5 に答える 5

5

malloc()/free() の不一致により、プロセスが完了した後でもメモリが永久に失われる可能性はありますか?

いいえ、と、およびfreeでさえ、この点で無害であり、プロセスが OS (この場合は SUSE Linux) を終了すると、すべてのメモリを要求します (まだ実行中の他のプロセスと共有されている場合を除く)。

C プログラム (C++ 以外) で、プログラムが完了した後、さらにはターミナル ウィンドウが閉じた後など、永続的なメモリ損失を引き起こす可能性のあるものは他に何ですか? 再起動するだけでメモリが元に戻ります。ファイルが閉じられずに問題が発生したという他の投稿を読んだことがありますが、その問題はないと思います。

malloc/free や mmap と同様に、プロセスによって開かれたファイルは、OS によって自動的に閉じられます。

大きなページのように永続的なメモリ リークの原因となるものはいくつかありますが、それらを使用している場合は、そのことを知っているはずです。それとは別に、いいえ。


ただし、「 free」とすぐに マークされないメモリをメモリ損失と定義すると、いくつかのことが発生する可能性があります。

  1. ディスクまたは mmap への書き込みは、RAM にしばらくキャッシュされる場合があります。OS は、ページをディスクに同期するまでページを保持する必要があります。
  2. プロセスによって読み取られたファイルは、OS が現在その RAM を使用する他に何もない場合、メモリに残る可能性があります。これは、すぐに必要になる可能性があり、既に RAM にあるコピーを読み取る方が速いという合理的な仮定に基づいています。繰り返しになりますが、OS または別のプロセスがその RAM の一部を必要とする場合は、すぐに破棄できます。

すべての RAM にお金を払った人として、OS がすべての RAM を常に使用することを望んでいることに注意してください。空き RAM は無駄な RAM です。


RAM の空き容量が少ない場合の主な問題は、RAM がオーバーコミットされている場合です。これは、システムで利用できるよりも多くのプロセス (および OS) が現在 RAM を要求または使用していることを意味します。プロセスで約 4Gb の RAM を使用しているように思えますが、これは問題になる可能性があります (OS にもかなりの量が必要であることを忘れないでください。しかし、十分な RAM があるようです!プロセスの半分の数を実行してみてください。良くなれば。

メモリ リークが原因で一時的なオーバーコミットが発生する場合があります。これについて調べることをお勧めします。プログラムのメモリ使用量を時間の経過とともにプロットしてみてください。メモリ使用量が継続的に増加する場合は、リークである可能性があります。

forkプロセスを ing すると、オリジナルに割り当てられたメモリを共有するコピーが作成されることに注意してください。しかし、あなたはそうしていません。

メモリ統計のトップとフリーを調べることは有効ですか、つまり、メモリの状況を正確に説明していますか? それらはプログラムの遅さに対応しているようです。


はい、メモリtopps確認するための完全に合理的な方法です。特に RES フィールドを観察します。今のところ、VIRT フィールドは無視してください。加えて:

システム全体がメモリで何をしているかを確認するには、次を実行します。

vmstat 10

プログラムの実行中およびその後しばらくの間。---memory---列に何が起こるかを見てください。

さらに、プロセスが終了したら、実行します

cat /proc/meminfo

そして、あなたの質問に結果を投稿してください。

プログラムのメモリ使用量が 4% しか表示されない場合、valgrind などでこの問題を検出できますか?

おそらくですが、非常に遅くなる可能性があり、この場合は実用的ではない可能性があります. electricfence など、プログラムの速度を著しく低下させないツールは他にもたくさんあります。私も過去に自分で巻いたことがあります。

于 2012-09-08T03:29:22.050 に答える
3

malloc()/free() はヒープで動作します。このメモリは、プロセスの終了時に OS に解放されることが保証されています。割り当てプロセスが特定の共有メモリ プリミティブ (System V IPC など) を使用して終了した後でも、メモリ リークが発生する可能性があります。しかし、私はこれが直接関係しているとは思いません。

少し戻って、負荷の軽い Linux サーバーからの出力を次に示します。

$ uptime
 03:30:56 up 72 days,  8:42,  2 users,  load average: 0.06, 0.17, 0.27
$ free -m
             total       used       free     shared    buffers     cached
Mem:         24104      23452        652          0      15821        978
-/+ buffers/cache:       6651      17453
Swap:         3811          5       3806

いいえ、652 MB しか無料ではありません! 右?違う。

Linux は、ブロック デバイス (ハード ドライブなど) にアクセスするたびに、未使用のメモリを探し、そこにデータのコピーを保存します。結局のところ、なぜですか?データはすでに RAM にあり、一部のプログラムは明らかにそのデータを必要としており、未使用の RAM は何の役にも立ちません。プログラムがやって来て、より多くのメモリを要求した場合、キャッシュされたデータは破棄されて空き容量が確保されます。

このfree出力の鍵は、1 行目ではなく 2 行目です。はい、23.4 GB の RAM が使用されていますが、必要なプログラムには 17.4 GB を使用できます。ヘルプを参照してください。Linux が RAM を食べてしまった! 多くのための。

プログラムが遅くなった理由はわかりませんが、「空きメモリ」メトリックが着実にゼロに低下するのは完全に正常であり、原因ではありません。

于 2012-09-08T03:40:49.077 に答える
1

オペレーティング システムは、絶対に必要なだけのメモリを解放します。メモリを解放することは、メモリが後で通常どおり使用される場合に無駄な労力になります。後でメモリを解放しなければならないためだけにメモリを解放するよりも、メモリをある用途から別の用途に直接移行する方が効率的です。

システムが空きメモリを必要とするのは、使用済みメモリをある目的から別の目的に切り替えることができないメモリを必要とする操作だけです。これは、ネットワーク割り込みの処理など、異常な操作の非常に小さなセットです。

このコマンドを入力sysctl vm.min_free_kbytesすると、空き容量が必要な KB 数がシステムから通知されます。おそらく100MB未満です。したがって、それ以上の金額を無料で持っていてもまったく問題ありません。

メモリをさらに解放したい場合は、コンピュータからメモリを取り外してください。それ以外の場合、オペレーティング システムは、それを使用するためのコストがゼロであると想定するため、無料にするメリットはありません。

たとえば、ディスクに書き込んだデータを考えてみましょう。オペレーティング システムは、そのデータを保持していたメモリを解放することができます。しかし、それは二重の損失です。ディスクに書き込んだデータを後で読み取る場合は、メモリから取得するだけでなく、ディスクから読み取る必要があります。そして、後でそのメモリが別の目的で必要になった場合は、メモリを解放するために行った作業をすべて元に戻す必要があります。うん。したがって、システムが空きメモリを絶対に必要としない場合、空きメモリは作成されません。

于 2012-09-08T03:25:22.817 に答える
0

私の推測では、問題はプログラムではなく、オペレーティングシステムにあります。OSは、最近使用したファイルのキャッシュを、再度アクセスすることを前提としてメモリに保持します。どのファイルが必要になるかは確実にはわからないため、保持したいファイルを犠牲にして、間違ったファイルを保持することを決定する可能性があります。

2回目の実行時に、最初の実行の出力ファイルがキャッシュされたままになっている可能性があります。これにより、2回目の実行でキャッシュを効果的に使用できなくなります。この理論をテストするには、最初の実行からすべてのファイルを削除し(キャッシュから解放する必要があります)、それによって2番目の実行が高速になるかどうかを確認します。

それでも問題が解決しない場合は、最初の実行でもすべての入力ファイルを削除してみてください。

于 2012-09-08T11:21:51.540 に答える
-1

回答

  1. はい、C または C++ では、解放されていないメモリを解放して OS に戻す必要はありません。
  2. メモリ マップされたファイルがあるか、削除されたファイルのファイル ハンドルなどを開いていますか。Linux は、へのすべての参照が割り当て解除されるまでファイルを削除しません。また、Linux は、ファイルを再度読み取る必要がある場合に備えて、ファイルをメモリにキャッシュします。OS が処理するため、ファイル キャッシュのメモリ使用量は無視できます。
  3. いいえ
  4. おそらく valgrind は、メモリがそうでないケースを強調します
于 2012-09-08T03:09:18.260 に答える