メモリオーバーコミット= 2

メモリオーバーコミット= 2

複数のメモリ集約プログラム(2〜5 GB)を連続して実行するコマンドを含むシェルスクリプトを実行しています。スクリプトの進捗状況を確認するために戻ったとき、Killed端末に報告されているように、いくつかのプロセスがあるという事実に驚きました。プログラムが後で開始される前に複数のプログラムが完了しましたが、Killedそれ以降のすべてのプログラムは分割エラーのために失敗します(これは私のコードのバグによるものでもそうではないかもしれません。読んでください)。

私が作業している特定のクラスタの使用履歴を調べたところ、誰かが同時に複数のメモリ集約型プロセスを実行し始め、その結果、クラスタで利用可能な物理メモリのすべてが使用されたことがわかりました。 )。私が理解できるように、これらのメモリ集約的なプロセスは、私のプログラムで問題が発生し始めたのと同時に実行され始めました。

メモリが足りなくなったときにLinuxは私のプログラムを終了できますか?後で発生した分割エラーは、私のコードのバグではなく、私のプログラムを実行するために使用できるメモリ不足によるものかもしれませんか?

答え1

それができます。

Linuxで発生する可能性があるメモリ不足の状況には2つあります。sysctl vm.overcommit_memory/proc/sys/vm/overcommit_memory)の値によって発生する状況が異なります。

要約:
カーネルは「メモリオーバーコミット」を実行できます。これは、カーネルが実際にシステムに存在するよりも多くのメモリをプログラムに割り当てる場合です。これは、プログラムが割り当てたすべてのメモリを実際に使用しないことを望んで行われます。これは非常に一般的な状況だからです。

メモリオーバーコミット= 2

overcommit_memoryに設定すると、2カーネルはオーバーコミットをまったく実行しません。逆に、プログラムにメモリが割り当てられると、そのメモリへのアクセスが保証されます。システムに割り当て要求を満たすのに十分な空きメモリがない場合、カーネルは要求失敗を返します。この状況を適切に処理することはプログラムに依存します。割り当てが実際に失敗したが、割り当てが成功したかどうかを確認しないと、アプリケーションでしばしば segfault が発生します。

segfaultの場合は、次の出力で次のような行を見つける必要がありますdmesg

[1962.987529] myapp[3303]: segfault at 0 ip 00400559 sp 5bc7b1b0 error 6 in myapp[400000+1000]

これはat 0、アプリケーションが初期化されていないポインタにアクセスしようとしていることを意味します。これは、失敗したメモリ割り当て呼び出しの結果である可能性があります(ただしこれが唯一の方法ではありません)。

過剰なメモリ使用量 = 0 と 1

またはovercommit_memoryに設定するとオーバーコミットが有効になり、プログラムは実際に使用可能なメモリよりも多くのメモリを割り当てることができます。01

しかし、プログラムが自分が割り当てたメモリを使用しようとしていますが、カーネルが実際にそれを満たすのに十分なメモリを持っていないことを発見した場合は、いくつかのメモリを取り戻す必要があります。まず、キャッシュフラッシュなど、さまざまなメモリクリーンアップ操作を試みますが、これが十分でない場合はプロセスを終了します。この終了はOOM-Killerによって行われます。 OOM-Killerはシステムを調査し、どのプログラムがどのメモリを使用しているのか、どれくらいの期間実行しているのか、誰が実行しているのか、そしてどのプログラムが終了するのかを決定する他の多くの要因を特定します。

プロセスが終了すると、使用中のメモリーが解放され、メモリー不足状態を引き起こしたプログラムが必要なメモリーを持つようになります。

ただし、このモードでもプログラムは依然として割り当て要求を拒否できます。overcommit_memoryisの場合、0カーネルは割り当て要求の拒否を開始する必要がある時点で最善の推測を試みます。に設定されている場合、1要求を拒否するタイミングを決定するためにどの決定を使用するのかわかりませんが、非常に大きな要求を拒否できます。

dmesg出力を表示し、次のメッセージを参照して、OOM-Killerが関連していることを確認できます。

[11686.043641] Out of memory: Kill process 2603 (flasherav) score 761 or sacrifice child
[11686.043647] Killed process 2603 (flasherav) total-vm:1498536kB, anon-rss:721784kB, file-rss:4228kB

答え2

実際には、どのような方法で見ても、つまりシステムのメモリマネージャによってプロセスがブロックされているかどうか、他の理由であれ、それは本当です。まだ間違い。メモリで処理したすべてのデータはどうなりますか?保存する必要があります。

これはLinux OOM管理を構成する最も一般的な方法ですが、overcommit_memory=プロセスごとに調整することもできます。たとえば、次のようになります。

echo [-+][n] >/proc/$pid/oom_adj

上記を使用すると、-17メモリ不足管理からそのプロセスが除外されます。おそらく一般的に良い考えではないでしょう。しかし、バグを探しているなら、試してみる価値があります。特にそれがOOMであるかどうかを知りたい場合は、さらにそうです。またはあなたのコード。この数を積極的に増やすと、OOMイベントでプロセスが終了する可能性が高くなります。これにより、メモリ不足の状況でコードの弾力性をさらに向上させ、必要に応じて正常にシャットダウンできます。

各プロセスのOOMハンドラの現在の設定を確認できます。たとえば、次のようになります。

cat /proc/$pid/oom_score 

そうでなければ自殺することができます。

sysctl vm.panic_on_oom=1
sysctl kernel.panic=X

メモリが不足すると、コンピュータが再起動します。X上記の時間をカーネルパニック後に再起動する前にコンピュータを停止する時間(秒単位)に設定します。野生に行きなさい。

何らかの理由で気に入ったと判断した場合は、絶えず使用してください。

echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=X" >> /etc/sysctl.conf

関連情報