web-dev-qa-db-ja.com

スワップが暴走するメモリ使用量によるシステムのフリーズ/無応答を防ぐ

プロセスが大量のメモリを必要とする場合、システムは他のすべてのプロセスをスワップファイルに移動します。それを含めて、X11サーバーや端末のような必要なプロセス。

そのため、プロセスが無制限に割り当てを続けると、そのプロセスがOOMキラーによって強制終了されるまで、すべてが応答しなくなります。私のラップトップは特に賢明であり、非常にひどく反応します。私はENTIRE HOURを使ってプロセスの終了を待っていましたが、その間にマウスカーソルさえ移動できませんでした。

どうすればこれを回避できますか?

1)スワップを無効にする=>私はしばしばたくさんのプロセスを起動し、その後それらが非アクティブになります。非アクティブなものはスワップに移動する必要があります。

2)SSD =>が高すぎる

3)最大メモリをulimit =>に設定しますが、プログラムが共振可能な大量のメモリを必要とする場合は失敗します。問題はそれがあまりにも多くを使用することではなく、それが他のプロセスを抑制することです。

4)重要なプログラム(X11、bash、kill、topなど)をメモリに保存し、決してそれらを入れ替えない=>これはできますか?どうやって?おそらく大規模なプログラムを交換するだけ?

5)?

39
BeniBela

TL、DR

短い一時/答え

  • 最も簡単:スワップパーティションを小さくして、遅いストレージからプロセスを実行することでメモリ制限がないという嘘をついてカーネルが実行しようとしないようにします。
    • 大きなスワップでは、OOM(out of memory manager)はすぐには行動を起こしません。通常、これは仮想メモリに基づいて計算され、私の過去の経験では、スワップ全体がいっぱいになるまで物事を殺しませんでした。したがって、スラッシングとクロールのシステムは...
  • 休止状態のために大きな交換が必要ですか?
    • 試行/問題あり:いくつかの制限を設定します(たとえばulimit -vを確認し、limits.confasオプションを使用してハードまたはソフト制限を設定します)。これは十分に機能していましたが、gigacageを導入したWebKitのおかげで、多くのgnomeアプリは今無制限のアドレススペースを期待して実行に失敗します!
    • 試行済み/問題あり:オーバーコミットのポリシーと比率は、これを管理および軽減するためのもう1つの方法です(例:sysctl vm.overcommit_memorysysctl vm.overcommit_ratio、ただし、この方法ではうまくいきませんでした)。
    • 難しい/複雑な:最も重要なプロセス(sshなど)にcgroupの優先順位を適用してみてください。ただし、これは現在cgroup v1にとっては面倒です(おそらくv2の方が簡単になるでしょう)...

私も見つけました:

長期的な解決策

上流のパッチが安定したディストリビューションのカーネルに入るのを待ってください。また、ディストリビューションベンダーがデスクトップのエディションでGUIの応答性を優先するためにカーネルのデフォルトを調整し、systemd cgroupをより有効に活用することを願っています。

興味深いパッチがいくつかあります。

したがって、ユーザースペースコードの悪さだけではなく、config/defaultのディストロを誤ったものにしています - カーネルがこれをより適切に処理できます。

既に検討されているオプションについてのコメント

1)スワップを無効にする

少なくとも小さなスワップパーティションを用意することをお勧めします( 最近のシステムでは本当にスワップが必要ですか? )。スワップを無効にすると、未使用ページのスワップアウトを防ぐだけでなく、メモリを割り当てるためのカーネルのデフォルトのヒューリスティックオーバーコミット戦略にも影響を与える可能性があります。( Overcommit_memory = 0のヒューリスティックとは何ですか? )、そのヒューリスティックはスワップページを当てにします。スワップがなければ、オーバーコミットは依然としてヒューリスティック(0)または常時(1)モードで機能する可能性がありますが、スワップなしとオーバーコミット戦略(2)の組み合わせはおそらく恐ろしい考えです。したがって、ほとんどの場合、スワップがないとパフォーマンスが低下する可能性があります。

たとえば、一時的な作業のために最初はメモリにアクセスするが、その後そのメモリを解放することに失敗し、バックグラウンドを実行し続ける長期実行プロセスについて考えます。プロセスが終了するまで、カーネルはそのためにRAMを使用する必要があります。スワップがなければ、カーネルは実際に積極的にRAMを使いたいと思う何か他のものにそれをページアウトすることはできません。また、何人の開発者が怠惰で、使用後に明示的にメモリを解放しないかについても考えてください。

3)最大メモリ制限を設定する

これはプロセスごとにのみ適用され、プロセスがシステムが物理的に持っている以上のメモリを要求するべきではないことはおそらく合理的な仮定です!それで、まだ寛大に設定されている間に、単独の狂ったプロセスがスラッシングを引き起こすのを止めることはおそらく役に立つでしょう。

4)重要なプログラム(X11、bash、kill、topなど)をメモリに保存し、それらを交換しないでください。

いい考えだが、それからそれらのプログラムは積極的に使用していないメモリを独占するだろう。プログラムが適度な量のメモリを要求するだけでよい場合もあります。

systemd 232リリース はこれを可能にするいくつかのオプションを追加しました:ユニット(サービス)を防ぐために 'MemorySwapMax = 0'を使うことができると思いますsshがメモリをスワップアウトしています。

それにもかかわらず、メモリアクセスを優先させることができればよりよいでしょう。

長い説明

Linuxカーネルはサーバーのワークロードに合わせて調整されているため、悲しいことにGUIの応答性が二次的な懸念事項となっています...デスクトップ版のUbuntu 16.04 LTSのカーネルメモリ管理設定は、他のサーバー版と変わらないようです。通常サーバーとして使用されているRHEL/CentOS 7.2のデフォルトにも一致します。

OOM、無制限、そして応答性のための整合性のトレードオフ

スワップスラッシング(メモリのワーキングセット、つまり与えられた短時間内に読み書きされるページが物理的なRAMを超える場合)は常にストレージI/Oをロックアップします - カーネルウィザードリィはプロセスを強制終了せずにシステムを節約できませんまたは2 ...

最近のカーネルでLinux OOMの微調整が行われ、このワーキングセットが物理メモリの状況を超えてプロセスを中止することを認識していることを願っています。そうでない場合、スラッシング問題が起こります。問題は、大きなスワップパーティションでは、カーネルがコミットしてメモリ要求を処理している間はシステムがまだヘッドルームを持っているように見えますが、ワーキングセットがスワップに溢れて効果的にストレージを処理しようとします。それはRAMです。

サーバー上では、決まった、遅い、データを失うな、トレードオフに対するスラッシングのパフォーマンスの低下を受け入れます。デスクトップでは、トレードオフは異なり、ユーザーは物事を即応させるために少しのデータ損失(プロセスの犠牲)を好むでしょう。

これは、OOMについてのニースコミカルなアナロジーでした: oom_pardon、別名、私のxlockを殺さないで

ちなみに、OOMScoreAdjustは重み付けを助け、より重要と考えられるOOMの殺害プロセスを避けるためのもう一つのsystemdオプションです。

バッファライトバック

" バックグラウンドでの書き戻しをしない "を実行すると、RAMを占有すると別のスワップアウトが発生するという問題を回避するのに役立ちます。ディスクへの一括書き込みとディスクへの一括書き込みは、IOを必要としている他の何かを停止します。それ自体が問題の原因となる問題ではありませんが、応答性の全体的な低下を招くことになります。

制限を制限する

Ulimitsに関する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リソース制御 オプションで設定できます。例えば。:

  • MemoryHigh
  • MemoryMax

他の便利なオプションは

  • アイオワイト
  • CPUSシェア

これらにはいくつかの欠点があります。

  1. オーバーヘッド。現在のdockerのドキュメントでは、1%の余分なメモリの使用と10%のパフォーマンスの低下について簡単に述べています(おそらくメモリ割り当て操作に関して - 実際には規定されていません)。
  2. Cgroup/systemd関連のものは最近かなり手直しされているので、上流の流束はLinuxディストリビューションベンダーがそれが最初に解決するのを待っているかもしれないことを意味します。

CGroup v2 では、彼らはmemory.highがプロセスグループによるメモリ使用を抑制し管理するための良いオプションであるべきであることを提案します。ただし、この見積もりでは、メモリのプレッシャー状況を監視するにはさらに作業が必要であることを示唆しています(2015年現在)。

ワークロードがより多くのメモリを必要としているかどうかを判断するには、メモリプレッシャー(メモリ不足のためにワークロードがどの程度影響を受けているか)を測定する必要があります。残念ながら、メモリプレッシャーモニタリングメカニズムはまだ実装されていません。

Systemdおよびcgroupのユーザースペースツールが複雑であることを考えると、適切なものを設定してこれをさらに活用する簡単な方法は見つかっていません。 Ubuntuのcgroupとsystemdのドキュメントは素晴らしいものではありません。将来の作業はデスクトップエディションのディストリビューションでcgroupsと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システムのメモリ制限の例

休止状態を有効にしたいので、大きなスワップパーティションが必要でした。そのため、ulimitなどで軽減しようとしています.

無制限

私は* hard as 16777216/etc/security/limits.d/mem.confに入れて、物理的に可能な量を超える単一のプロセスがより多くのメモリを要求することを許可しないようにしました。スラッシングを一斉に防ぐことはできませんが、貪欲なメモリ使用を伴う単一のプロセス、またはメモリリークが原因でスラッシングが発生する可能性があります。例えば。 Exchangeサーバからグローバルアドレスリストを更新するなどの日常的なことをしているとき、gnome-contactsが8GB以上のメモリを消費するのを私は見ています...

Gnome contacts chewing up RAM

ulimit -S -vで見られるように、多くのディストリビューションでは、このハードおよびソフト制限が「無制限」に設定されています。理論的には、プロセスは大量のメモリを要求しますがサブセットのみを積極的に使用します。RAMシステムには16GBしかありません。上記の厳しい制限により、カーネルが欲張りな投機的メモリ要求を拒否したときに、正常に実行できた可能性があるプロセスを中止することができます。

しかし、それはまた、gnomeの連絡先のような非常識なことを捉え、私のデスクトップの応答性を失う代わりに、 "not enough free memory"エラーを受け取ります。

enter image description here

アドレス空間(仮想メモリ)の合併症設定ulimit

残念ながら、仮想メモリのふりをするのを好む開発者の中には無限のリソースであり、仮想メモリに制限を設定すると一部のアプリが壊れる可能性があります。例えば。 WebKit(いくつかのgnomeアプリが依存しています)は、ちょっとしたヒントFATAL: Could not allocate gigacage memoryが発生するという稀な量の仮想メモリとMake sure you have not set a virtual memory limitエラーを割り当てようとするgigacageセキュリティ機能を追加しました。回避策GIGACAGE_ENABLED=noはセキュリティ上の利点を放棄しますが、同様に、仮想メモリの割り当てを制限することを許可されていないこともセキュリティ機能(サービス拒否を防ぐことができるリソース制御など)を放棄します。皮肉なことに、gigacageとgnome devの間では、メモリ割り当てを制限すること自体がセキュリティ管理であることを忘れているようです。そして残念なことに、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に戻すことにしました。

41
JPvRiel