TL; DR
短い一時/回答
- 最も簡単:スワップパーティションを小さくし、低速のストレージからプロセスを実行することでメモリの制限がないという嘘に追いつくカーネルを避けます。
- 大きなスワップでは、OOM(out of memory manager)はすぐにアクションを実行しません。通常、仮想メモリに基づいて説明され、過去の経験では、スワップ全体がいっぱいになるまで物を殺しませんでした。したがって、スラッシングとクロールのシステムは...
- 休止状態に大きなスワップが必要ですか?
- 試行/問題:いくつかのulimitsを設定します(例:をチェック
ulimit -v
し、のas
オプションを使用してハードまたはソフトの制限を設定しますlimits.conf
)。これは以前は十分に機能していましたが、WebKitを導入したおかげでgigacage
、多くのgnomeアプリは無制限のアドレススペースを期待して実行できなくなりました!
- 試行/問題:オーバーコミットポリシーと比率は
sysctl vm.overcommit_memory
、これを管理および軽減しようとする別の方法です(たとえば、sysctl vm.overcommit_ratio
このアプローチはうまくいきませんでした。
- 難しい/複雑な:最も重要なプロセス(例えばssh)にcgroup優先度を適用してみてください。しかし、これは現在cgroup v1にとって扱いにくいようです(願わくばv2でもっと簡単になります)...
私も見つけました:
長期的なソリューション
いくつかのアップストリームパッチが安定したディストリビューションカーネルに入るのを待ちます。また、ディストリビューションベンダーがカーネルのデフォルトをより適切に調整し、systemd cgroupを活用してデスクトップエディションのGUIの応答性を優先することを期待します。
興味のあるパッチ:
だから、悪いのはユーザースペースのコードやディストリビューションの設定/デフォルトだけではありません-カーネルはこれをうまく処理できます。
すでに検討されているオプションに関するコメント
1)スワップを無効にします
少なくとも小さなスワップパーティションを用意することをお勧めします(最新のシステムでは本当にスワップが必要ですか?)。スワップを無効にすると、未使用ページのスワップアウトが防止されるだけでなく、メモリを割り当てるためのカーネルのデフォルトのヒューリスティックオーバーコミット戦略にも影響する可能性があります(Overcommit_memoryのheuristics = 0はどういう意味ですか?)。スワップがなくても、オーバーコミットはおそらくヒューリスティック(0)モードまたは常時(1)モードで機能しますが、スワップなしとネバー(2)オーバーコミット戦略の組み合わせは恐ろしい考えです。そのため、ほとんどの場合、スワップはパフォーマンスを低下させません。
たとえば、一度限りの作業のために最初はメモリにアクセスした後、そのメモリの解放に失敗してバックグラウンドを実行し続ける長時間実行プロセスについて考えます。プロセスが終了するまで、カーネルはそのためにRAMを使用する必要があります。スワップなしでは、カーネルは実際にRAMを積極的に使用したい何かのためにそれをページアウトすることはできません。また、いくつの開発者が怠け者であり、使用後にメモリを明示的に解放しないかを考えます。
3)最大メモリulimitを設定する
これはプロセスごとにのみ適用され、おそらくシステムが物理的に持っているより多くのメモリをプロセスが要求するべきではないという合理的な仮定です!そのため、たった1つのクレイジーなプロセスがスラッシングをトリガーするのを止めながら、寛大に設定することはおそらく有用です。
4)重要なプログラム(X11、bash、kill、top、...)をメモリに保持し、それらをスワップしない
良いアイデアですが、それらのプログラムは積極的に使用していないメモリを独占します。プログラムが適度な量のメモリのみを要求する場合は、許容される場合があります。
systemd 232リリースでは、これを可能にするいくつかのオプションが追加されました。「MemorySwapMax = 0」を使用して、sshのようなユニット(サービス)がメモリをスワップアウトするのを防ぐことができると思います。
それにもかかわらず、メモリアクセスに優先順位を付けることができる方が良いでしょう。
長い説明
Linuxカーネルはサーバーワークロード用に調整されているため、GUIの応答性は悲しいことに副次的な懸念事項です。Ubuntu16.04 LTSのデスクトップエディションのカーネルメモリ管理設定は、他のサーバーエディションと変わらないようです。サーバーとして通常使用されるRHEL / CentOS 7.2のデフォルトと一致します。
OOM、ulimit、および応答性のための整合性のトレードオフ
スワップスラッシング(メモリのワーキングセット、つまり特定の短い時間フレームで読み書きされるページが物理RAMを超えるとき)は常にストレージI / Oをロックします-カーネルウィザードはプロセスを強制終了せずにこれからシステムを保存できませんまたは2 ...
最近のカーネルでLinux OOMの調整が行われ、このワーキングセットが物理メモリの状況を超えており、プロセスを強制終了することを認識しています。そうでない場合、スラッシングの問題が発生します。問題は、大きなスワップパーティションでは、カーネルがコミットを十分に超過し、メモリ要求を処理している間、システムにまだヘッドルームがあるように見えることがありますが、ワーキングセットがスワップにあふれて、ストレージを効果的に処理しようとする可能性がありますそれはRAMです。
サーバー上では、スラッシングによるパフォーマンスのペナルティを受け入れますが、それは決定的な低速でデータを失わないでください。デスクトップでは、トレードオフが異なり、ユーザーは、物事の応答性を保つために、少しのデータ損失(プロセスの犠牲)を好むでしょう。
これはOOMについての素晴らしいコミカルな類推でした:oom_pardon、別名私のロックを殺さないでください
ちなみに、OOMScoreAdjust
より重要と見なされるOOMの強制終了プロセスを軽減し回避するためのもう1つのsystemdオプションです。
バッファリングされたライトバック
「バックグラウンドライトバックを吸わないようにする」ことは、RAMを占有するプロセスが別のスワップアウト(ディスクへの書き込み)を引き起こし、ディスクへの一括書き込みがIOを必要とする他のすべてを停止させる問題を回避するのに役立つと思います。これはスラッシングの問題自体の原因ではありませんが、応答性の全体的な低下につながります。
制限の制限
ulimitの問題の1つは、アカウンティングが仮想メモリアドレススペースに適用されることです(これは、物理スペースとスワップスペースの両方を組み合わせることを意味します)。としてman limits.conf
:
rss
maximum resident set size (KB) (Ignored in Linux 2.4.30 and
higher)
したがって、物理RAMの使用量にのみ適用するようにulimitを設定することは、もはや使用可能に見えません。したがって
as
address space limit (KB)
唯一の尊敬されている調整可能パラメータのようです。
不幸なことに、WebKit / Gnomeの例で詳しく説明しているように、仮想アドレススペースの割り当てが制限されている場合、一部のアプリケーションは実行できません。
cgroupsは将来役立つでしょうか?
現在、面倒ですが、いくつかのカーネルcgroupフラグを有効にすることは可能です cgroup_enable=memory swapaccount=1
(たとえばgrub configで)、cgroupメモリコントローラーを使用してメモリの使用を制限することができます。
cgroupには、「ulimit」オプションよりも高度なメモリ制限機能があります。CGroup v2は、ulimitsの機能を改善する試みのヒントを示しています。
メモリーとスワップを組み合わせたアカウンティングと制限は、スワップ空間の実際の制御に置き換えられます。
CGroupオプションは、systemdリソース制御オプションを介して設定できます。例えば:
他の便利なオプションは
これらにはいくつかの欠点があります。
- オーバーヘッド。現在のdockerのドキュメントでは、1%の余分なメモリ使用と10%のパフォーマンス低下について簡単に言及しています(おそらくメモリ割り当て操作に関して-実際には指定していません)。
- Cgroup / systemdのものは最近大幅に作り直されたため、アップストリームの流動性はLinuxディストリビューションベンダーが最初に解決するのを待っている可能性があることを意味します。
cgroup v2では、彼らはそれが示唆memory.high
スロットルに良い選択肢とプロセスグループでメモリ使用量を管理する必要があります。ただし、この引用は、メモリ不足の状況を監視するには、さらに作業が必要であることを示唆しています(2015年時点)。
ワークロードがより多くのメモリを必要とするかどうかを判断するには、メモリ不足の測定値-メモリ不足によりワークロードがどれだけ影響を受けているかが必要です。残念ながら、メモリプレッシャーモニタリングメカニズムはまだ実装されていません。
systemdとcgroupのユーザースペースツールは複雑であるため、適切なものを設定してこれをさらに活用する簡単な方法は見つかりませんでした。Ubuntuのcgroupとsystemdのドキュメントはあまり良くありません。将来の作業は、デスクトップエディションを備えたディストリビューションがcgroupとsystemdを活用し、高いメモリのプレッシャーの下で、sshとX-Server /ウィンドウマネージャーコンポーネントがCPU、物理RAM、ストレージIOへの優先順位の高いアクセスを取得して、プロセスとの競合を回避することです忙しいスワッピング。カーネルのCPUおよびI / O優先機能は、しばらく前から存在していました。不足しているのは、物理RAMへの優先アクセスのようです。
ただし、CPUとIOの優先順位さえ適切に設定されていません!?systemdのcgroupの制限、適用されたcpuの共有などを確認したとき、私が知る限り、Ubuntuは事前に定義された優先順位を付けていませんでした。例えば、私は走った:
systemctl show dev-mapper-Ubuntu\x2dswap.swap
それをssh、samba、gdm、nginxの同じ出力と比較しました。GUIやリモート管理コンソールなどの重要なものは、スラッシングが発生したときに他のすべてのプロセスと同等に戦わなければなりません。
16GB RAMシステムのメモリ制限の例
休止状態を有効にしたかったので、大きなスワップパーティションが必要でした。したがって、ulimitsなどで軽減しようとしています。
限界
私が入れ* hard as 16777216
に/etc/security/limits.d/mem.conf
単一のプロセスが物理的に可能であるよりも多くのメモリを要求することが許されないであろうというように。スラッシングをすべて防ぐことはできませんが、貪欲なメモリ使用またはメモリリークのある単一のプロセスだけでスラッシングが発生する可能性があります。たとえばgnome-contacts
、Exchangeサーバーからグローバルアドレス一覧を更新するなどのありふれた作業を行うと、8 GB以上のメモリを消費します。
で見られるように ulimit -S -v
、多くのディストリビューションではこのハードとソフトの制限を「無制限」に設定しています。理論的には、プロセスは大量のメモリを要求することができますが、サブセットを積極的に使用するだけで、24GBのRAMが与えられていると喜んで実行されますシステムには16GBしかありません。上記のハード制限により、カーネルが貪欲な投機的メモリ要求を拒否すると、正常に実行できた可能性のあるプロセスが中止されます。
ただし、gnomeの連絡先などの異常なものもキャッチし、デスクトップの応答性を失う代わりに、「空きメモリが不足しています」というエラーが表示されます。
アドレス空間(仮想メモリ)のulimitを設定する複雑さ
残念ながら、仮想メモリは無限のリソースであると偽装したい開発者もいます。仮想メモリにulimitを設定すると、一部のアプリが破損する可能性があります。たとえば、WebKit(一部のgnomeアプリが依存します)は、異常gigacage
な量の仮想メモリを割り当てようとするセキュリティ機能を追加しました。回避策、FATAL: Could not allocate gigacage memory
Make sure you have not set a virtual memory limit
GIGACAGE_ENABLED=no
セキュリティ上の利点はありませんが、同様に、仮想メモリの割り当てを制限することはセキュリティ機能もありません(たとえば、サービス拒否を防ぐことができるリソース制御)。皮肉なことに、ギガケージとgnomeの開発者の間では、メモリ割り当ての制限自体がセキュリティ管理であることを忘れているようです。悲しいことに、gigacageに依存しているgnomeアプリは、より高い制限を明示的に要求することに煩わされていないことに気付きました。
公平に言うと、カーネルが仮想メモリの代わりに常駐メモリの使用に基づいてメモリ割り当てを拒否できるようになった場合、仮想メモリが無制限であると装う方が危険は少なくなります。
オーバーコミット
アプリケーションがメモリアクセスを拒否され、オーバーコミットを停止したい場合は、以下のコマンドを使用して、メモリの負荷が高い場合のシステムの動作をテストします。
私の場合、デフォルトのコミット率は次のとおりです。
$ sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50
ただし、ポリシーを変更してオーバーコミットを無効にし、比率を適用する場合にのみ完全に有効になります
sudo sysctl -w vm.overcommit_memory=2
この比率は、全体で24GBのメモリしか割り当てられないことを暗示しています(16GB RAM * 0.5 + 16GB SWAP)。そのため、おそらくOOMが表示されることは決してなく、事実上、プロセスがスワップでメモリに絶えずアクセスする可能性は実質的に低くなります。しかし、システム全体の効率も犠牲にする可能性があります。
開発者がメモリ割り当て要求を拒否するOSを適切に処理しないことが一般的であるため、これにより多くのアプリケーションがクラッシュします。これは、スラッシング(ハードリセット後にすべての作業が失われる)によりロックアップが引き出されることのあるリスクを、さまざまなアプリがクラッシュするより頻繁なリスクとトレードオフします。私のテストでは、システムがメモリ不足に陥り、メモリを割り当てることができなかったときにデスクトップ自体がクラッシュしたため、あまり役に立ちませんでした。ただし、少なくともコンソールとSSHは引き続き機能しました。
VMのオーバーコミットメモリの動作について詳しくはこちらをご覧ください。
sudo sysctl -w vm.overcommit_memory=0
デスクトップのグラフィカルスタック全体とその中のアプリケーションがそれでもクラッシュすることを考えると、このためにデフォルトに戻すことを選択しました。