スラッシングの原因となっているプロセス(メモリの過剰割り当てが原因)をすばやく停止するにはどうすればよいですか?


19

私たちは皆それを経験しました-いくつかのプログラムは、大量のメモリを必要とする何かをするように求められます。このメモリすべてを忠実に割り当てようとすると、システムは即座にスラッシングを開始し、無限にスワップし、反応が遅くなるか応答しなくなります。

Matlabスクリプトが途方もなく巨大なマトリックスを割り当てようとしたため、最近、Ubuntuラップトップでこれを経験しました。〜5分以上スラッシングした後、コンソールでCtrl-F1を押してMatlabを強制終了できました。システムをすぐに制御し、問題のあるプロセスを強制終了できるようにするホットキーが必要です。または、おそらく、このような大きなバッファの割り当てを単に黙って拒否します。

  1. 過剰なスワッピングにより応答しなくなったり、極端に遅くなったLinuxシステムの制御を回復する最も速い方法は何ですか?

  2. たとえば、プロセスが割り当てることを許可されているメモリの量を制限することによって、そのようなスワッピングが最初に発生するのを防ぐ効果的な方法はありますか?

回答:


12

Alt-SysRq-Fを押して、ほとんどのメモリを使用してプロセスを強制終了します。

  • 通常、SysRqキーはPrintキーにマップされます。
  • グラフィカルデスクトップを使用している場合、Alt-SysRqを押すと別のアクション(スナップショットプログラムなど)がトリガーされる場合は、Ctrl-Alt-SysRq-Fを押す必要があります。
  • ラップトップを使用している場合は、ファンクションキーも押す必要があります。
  • 詳細については、ウィキペディアの記事を参照してください

5

この目的のためにスクリプトを作成しました-https://github.com/tobixen/thrash-protect

実稼働サーバー、ワークステーション、ラップトップでこのスクリプトを実行し、成功しました。このスクリプトはプロセスを強制終了しませんが、一時的に停止します。この単純なスクリプトではない場合、スラッシングによって制御が失われると確信する状況がいくつかあります。「最悪」の場合、問題のプロセスはかなり遅くなり、最終的にカーネル(OOM)によって殺されます。「最良」の場合、問題のプロセスは実際に完了します...いずれにしても、サーバーまたはワークステーション状況の調査が容易になるように、比較的応答性が高くなります。

もちろん、「より多くのメモリを購入する」または「スワップを使用しない」は、「スラッシングを回避する方法」という質問に対するより伝統的な回答の2つの選択肢ですが、一般的にはうまく動作しない傾向があります(より多くのメモリをインストールすると、些細なことではなく、不正なプロセスはインストールされた量に関係なくすべてのメモリを使い果たし、バッファリング/キャッシングに十分なメモリがない場合はスワップしなくてもスラッシングの問題に陥ることがあります)。スラッシュ保護に加えて、大量のスワップ領域をお勧めします。


スワップの無効化については、unix.stackexchange.com / a / 24646/9108によると、最適なオプションではない可能性があります。
sashoalm

確かに、誰かが私に同じコメントをしたので、その時点でスラッシュ保護ドキュメントを変更しました。
tobixen

4
  1. 過剰なスワッピングにより応答しなくなったり、極端に遅くなったLinuxシステムの制御を回復する最も速い方法は何ですか?

Alt-SysRq-Fで既に回答済み

  1. たとえば、プロセスが割り当てることを許可されているメモリの量を制限することによって、そのようなスワッピングが最初に発生するのを防ぐ効果的な方法はありますか?

私はこの第2部に答えています。はい、ulimitそれでも単一のプロセスを制限するのに十分に機能します。あなたはできる:

  • 制御不能になる可能性があることがわかっているプロセスにソフト制限を設定する
  • 追加の保険が必要な場合は、すべてのプロセスにハード制限を設定します

また、簡単に述べたように:

CGroupsを使用して、リソースの使用を制限し、そのような問題を防ぐことができます

確かに、cgroupsはより高度な制御を提供しますが、私の意見では現在、構成がより複雑です。

古い学校のulimit

オフになったら

以下に簡単な例を示します。

$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)

それ:

  • 1GBの全体的なメモリ使用のソフト制限を設定します(ulimitはkB単位の制限を想定しています)
  • 再帰的にbash関数呼び出しr2(){ r2 $@$@;};r2 r2を実行します。これは、スタックメモリを要求している間に無限に倍増することにより、CPUとRAMを指数関数的に噛みます。

ご覧のとおり、1GB以上を要求しようとすると停止しました。

-v仮想メモリの割り当て(合計、つまり物理+スワップ)で動作することに注意してください。

永久保護

仮想メモリの割り当てを制限するにasは、と同等-vですlimits.conf

単一の不正なプロセスから保護するために、次のことを行います。

  • すべてのプロセスにハードアドレス空間の制限を設定します。
  • address space limit = <physical memory> - 256MB
  • したがって、貪欲なメモリ使用やアクティブループとメモリリークのある単一のプロセスが、すべての物理メモリを消費することはありません。
  • 256MBのヘッドルームは、sshまたはコンソールでの重要な処理に使用できます。

一発ギャグ:

$ sudo bash -c "echo -e \"*\thard\tas\t$(($(grep -E 'MemTotal' /proc/meminfo | grep -oP '(?<=\s)\d+(?=\skB$)') - 256*2**10))\" > /etc/security/limits.d/mem.conf"

検証するには、これにより次の結果が得られます(16GBシステムなど):

$ cat /etc/security/limits.d/mem.conf
*   hard    as      16135196
$ ulimit -H -v
161351960

ノート:

  • メモリを使用して1つのプロセスがオーバーボードするのを緩和するだけです。
  • マルチプロセスワークロードがスラッシングの原因となる大きなメモリプレッシャーを防ぐことはありません(cgroupsがその答えです)。
  • rsslimits.confでオプションを使用しないでください。新しいカーネルでは尊重されていません。
  • 保守的です。
    • 理論的には、プロセスは投機的に多くのメモリを要求できますが、サブセットのみを積極的に使用します(より小さなワーキングセット/常駐メモリの使用)。
    • 上記のハード制限により、そのようなプロセスは中止されます(Linuxが仮想メモリアドレス空間のオーバーコミットを許可している場合は、正常に実行されていたとしても)。

新しいCGroups

より多くの制御を提供しますが、現在はより複雑です:

  • ulimitオファリングの改善。
    • memory.max_usage_in_bytes 物理メモリを個別に考慮および制限できます。
    • 一方ulimit -mおよび/またはrsslimits.conf同様の機能を提供するためのもの、それはカーネルのLinux 2.4.30以降の仕事をしませんしました!
  • ブートローダーでいくつかのカーネルcgroupフラグを有効にする必要があります:cgroup_enable=memory swapaccount=1
    • これは、Ubuntu 16.04ではデフォルトでは発生しませんでした。
    • おそらく、余分なアカウンティングオーバーヘッドのパフォーマンスへの影響が原因です。
  • cgroup / systemdのものは比較的新しく、かなり変更されているため、アップストリームのフラックスは、Linuxディストリビューションベンダーがまだ使いやすくしていないことを意味します。14.04LTSと16.04LTSの間で、cgroupを使用するためのユーザー空間ツールが変更されました。
    • cgm 現在、公式にサポートされているユーザースペースツールのようです。
    • systemdユニットファイルには、sshのような重要なサービスに優先順位を付けるための事前定義された「ベンダー/ディストリビューション」デフォルトはまだないようです。

たとえば、現在の設定を確認するには:

$ echo $(($(cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes) / 2**20)) MB
11389 MB
$ cat /sys/fs/cgroup/memory/memory.stat
...

たとえば、単一プロセスのメモリを制限するには:

$ cgm create memory mem_1G
$ cgm setvalue memory mem_1G memory.limit_in_bytes $((1*2**30))
$ cgm setvalue memory mem_1G memory.memsw.limit_in_bytes $((1*2**30))
$ bash
$ cgm movepid memory mem_1G $$
$ r2(){ r2 $@$@;};r2 r2
Killed

バックグラウンドプロセスとしてRAMを噛み締めてから強制終了する動作を確認するには:

$ bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2' & while [ -e /proc/$! ]; do ps -p $! -o pcpu,pmem,rss h; sleep 1; done
[1] 3201
 0.0  0.0  2876
 102  0.2 44056
 103  0.5 85024
 103  1.0 166944
 ...
98.9  5.6 920552
99.1  4.3 718196
[1]+  Killed                  bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2'

メモリリクエストの指数関数的な増加(2のべき乗)に注意してください。

将来、SSHやグラフィカルスタックなどの重要なもののcgroupの優先度と制限を事前に設定する「ディストリビューション/ベンダー」を見て、メモリが枯渇しないようにしましょう。


2

Ctrl- を押しzてプログラムを一時停止することができます。その後kill %1、(またはジョブ番号が何であれ、PIDを使用できます)できます。

このulimitコマンドを使用して、プロセスで使用可能なメモリの量を制限することができます。


Ctrl-Zは便利ですが、通常、Matlab GUIを実行していて、制御端末を追跡できなくなっているため、Ctrl-Zキーを押す簡単な方法はありません。GUIに、フォーカスがあるアプリケーションにSIGSTOPを送信するためのホットキーがあると便利です。
nibot

kill -STOP <pid>Ctrl-Zと同じことを実行できます。
hlovdal

はい、しかし、全体的な問題は、そのような状況では、システムが非常に応答しないため、コマンドプロンプトに到達するまでに長時間(または永久に)時間がかかることです。
nibot

1

CGroupsを使用して、リソースの使用を制限し、そのような問題を防ぐことができます:https : //en.wikipedia.org/wiki/Cgroups


回答に重要な情報を含め、帰属と詳細な読書のためだけにリンクを使用してください。そのリンクはCGroupsが何であるかを説明していますが、リンクから実際にそれを使用して問題を解決する方法は明らかではありません。質問の解決策を説明するために回答を展開できますか?ありがとう。
fixer1234

0

GUIに、フォーカスがあるアプリケーションにSIGSTOPを送信するためのホットキーがあると便利です。

常に古典的なxkillコマンドがあります(私のシステムのxorg-x11-apps-7.4-14.fc14.src.rpmから)。ターゲットウィンドウを強制終了する代わりにSIGSTOPを送信するクローンを作成するのはそれほど難しくないはずです。


いくつかのキーの組み合わせを押すと、xkillをすばやく起動できますか?
-nibot

私はわかりません。gnomeとKDEの両方に、プログラムを起動するために使用できるいくつかのグローバルショートカット機能があると思います。
-hlovdal
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.