解決策 1:
設定 overcommit_ratio
80 にするのは適切なアクションではない可能性があります。値を 100 未満に設定することは、ほとんどの場合正しくありません。
これは、Linux アプリケーションが実際に必要以上に割り当てるためです。 2 文字のテキストを格納するために 8kb を割り当てるとします。それは数KBの未使用です。アプリケーションはこれを頻繁に行います。オーバーコミットはそのために設計されています。
したがって、基本的にオーバーコミットが 100 の場合、カーネルはアプリケーションがあなたが持っている以上のメモリを割り当てることを許可しません (スワップ + RAM)。 100 未満に設定すると、メモリをすべて使用することはありません。この設定を行う場合は、前述のシナリオが非常に一般的であるため、100 より大きい値に設定する必要があります。
さて、OOMキラーのトリガーに関する問題については、オーバーコミットを手動で設定しても、おそらくこれは修正されません。デフォルト設定 (ヒューリスティック決定) はかなりインテリジェントです。
これが本当に問題の原因かどうかを確認したい場合は、/proc/meminfo
を見てください。 OOMキラーが実行されたとき。 Committed_AS
が表示された場合 CommitLimit
に近い 、しかし free
まだ使用可能な空きメモリが表示されている場合は、シナリオに合わせてオーバーコミットを手動で調整できます。この値を低く設定しすぎると、空きメモリがまだ十分にあるときに、OOM キラーがアプリケーションを強制終了し始めます。設定が高すぎると、ランダムなアプリケーションが、割り当てられたメモリを使用しようとしたときに、実際には使用できない (すべてのメモリが実際に使い果たされた場合) ときに、アプリケーションが停止する可能性があります。
解決策 2:
@dunxdが言及しているドキュメントのセクション9.6「オーバーコミットとOOM」は、オーバーコミットを許可することの危険性について特にグラフィックです。ただし、80
私も面白そうだったので、いくつかテストを行いました。
私が見つけたのは overcommit_ratio
すべてのプロセスで使用できる合計 RAM に影響します。ルート プロセスは、通常のユーザー プロセスと異なる扱いを受けていないようです。
比率を 100
に設定 以下は、malloc/sbrk
から値を返す従来のセマンティクスを提供する必要があります。 信頼できます。 100
より低い比率に設定する キャッシングなどの非プロセス アクティビティ用により多くの RAM を予約する方法かもしれません。
したがって、24 GiB の RAM を搭載した私のコンピューターでは、スワップが無効になっており、9 GiB が使用され、top
が使用されています。 表示中
Mem: 24683652k total, 9207532k used, 15476120k free, 19668k buffers
Swap: 0k total, 0k used, 0k free, 241804k cached
ここにいくつかの overcommit_ratio
があります 設定と、RAM コンシューマ プログラムが取得できる RAM の量 (各ページにアクセス) - いずれの場合も、プログラムは 1 回 malloc
正常に終了しました。 失敗しました。
50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
一度にいくつかを実行しても、一部を root ユーザーとして実行しても、それらが一緒に消費した合計量は変わりませんでした。最後の 3+ GiB 程度を消費できなかったのは興味深いことです。 free
ここに表示されている値を大幅に下回ることはありませんでした:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
実験は面倒でした - すべての RAM が使用されている瞬間に malloc を使用するものはすべてクラッシュする傾向があります。多くのプログラマーは C で malloc の失敗をチェックするのが苦手であり、一部の人気のあるコレクション ライブラリはそれを完全に無視し、C++ やその他のさまざまな言語も同様です。
私が見た架空の RAM の初期の実装のほとんどは、1 つの大きなプロセス (たとえば、使用可能なメモリの 51% 以上) が fork()
に必要な、非常に特殊なケースを処理するものでした。 exec()
するために いくつかのサポート プログラムで、通常ははるかに小さいものです。コピー オン ライト セマンティクスを備えた OS では、fork()
が許可されます。 ただし、フォークされたプロセスが実際にあまりにも多くのメモリ ページを変更しようとした場合 (各ページは、最初の巨大なプロセスから独立した新しいページとしてインスタンス化する必要があります)、強制終了されることになります。親プロセスは、より多くのメモリを割り当てる場合にのみ危険にさらされ、場合によっては、他のプロセスが停止するのを少し待ってから続行するだけで、不足を処理できます。子プロセスは通常、 exec()
を介して (通常はより小さな) プログラムに置き換えられました。 その後、但し書きはありませんでした。
Linux のオーバーコミットの概念は、fork()
の両方を許可する極端なアプローチです。 発生するだけでなく、単一のプロセスが大量に過剰に割り当てられる可能性があります。 OOM キラーによる死亡は、実行する プログラムであっても、非同期に発生します。 責任を持ってメモリ割り当てを処理します。私は個人的にシステム全体が嫌いです オーバーコミット全般、特に oom-killer - ライブラリに感染し、ライブラリを使用するすべてのアプリを介して感染するメモリ管理へのデビル メイ ケア アプローチを助長します。
比率を 100 に設定し、スワップ パーティションも用意することをお勧めします。これは、通常、巨大なプロセスによってのみ使用されることになります。プロセスは、スワップに詰め込まれる部分のほんの一部しか使用しないことが多いため、 OOMキラーの誤機能からプロセスの大部分を保護します。これにより、ウェブサーバーがランダムな死から安全に保たれ、malloc
を処理するように記述されている場合 責任を持って、自殺しても安全です (ただし、後者に賭けないでください)。
つまり、これを /etc/sysctl.d/10-no-overcommit.conf
で使用しています
vm.overcommit_memory = 2
vm.overcommit_ratio = 100