私たちは皆それを経験しました-あるプログラムは大量のメモリを必要とする何かをするように頼まれます。このすべてのメモリを忠実に割り当てようとすると、システムはすぐにスラッシングを開始し、無限にスワップし、速度が低下したり応答しなくなったりします。
私は最近、Matlabスクリプトが途方もなく巨大なマトリックスを割り当てようとしたためにUbuntuラップトップでこれを経験しました。約5分以上のスラッシングの後、コンソールにCtrl-F1を押して、Matlabを強制終了することができました。むしろ、システムをすぐに制御でき、問題のあるプロセスを強制終了できるホットキーが必要です。または、おそらく、そのような大きなバッファの割り当てを黙って拒否します。
過度のスワッピングが原因で応答しなくなったり、極端に遅くなったりしたLinuxシステムの制御を取り戻すための最も簡単な方法は何ですか?
プロセスが割り当てを試みることができるメモリの量を制限するなどして、そもそもそのようなスワッピングが発生するのを防ぐ効果的な方法はありますか?
Alt-SysRq-Fを押して、最も多くのメモリを使用しているプロセスを強制終了します。
この目的のためにスクリプトを作成しました- https://github.com/tobixen/thrash-protect
私はこのスクリプトを本番サーバー、ワークステーション、ラップトップで実行して成功しました。このスクリプトはプロセスを強制終了しませんが、一時的に一時停止します-この単純なスクリプトがなかった場合、スラッシングが原因で制御を失ったと確信している状況が後でいくつかありました。 「最悪の」場合、問題のあるプロセスは大幅に遅くなり、最終的にカーネル(OOM)によって強制終了されます。「最良の」場合、問題のあるプロセスは実際に完了します...いずれの場合も、サーバーまたはワークステーション状況の調査が容易になるように、比較的応答性が高くなります。
もちろん、「メモリを追加購入する」または「スワップを使用しない」は、「スラッシングを回避する方法」という質問に対する2つの代替の、より伝統的な回答ですが、一般的にはうまく機能しない傾向があります(メモリを追加すると、些細なことではありませんが、不正なプロセスは、インストールされているメモリの量に関係なくすべてのメモリを消費する可能性があり、バッファリング/キャッシュに十分なメモリがない場合、スワップがなくてもスラッシングの問題が発生する可能性があります。スラッシュプロテクトとたくさんのスワップスペースをお勧めします。
- 過度のスワッピングが原因で応答しなくなったり、極端に遅くなったりしたLinuxシステムの制御を取り戻すための最も簡単な方法は何ですか?
すでに上記でAlt-SysRq-Fで回答済み
- プロセスが割り当てを試みることができるメモリの量を制限するなど、そもそもそのようなスワッピングが発生するのを防ぐ効果的な方法はありますか?
私はこの第2部に答えています。はい、ulimit
は、単一のプロセスを制限するのに十分に機能します。あなたはできる:
また、簡単に述べたように:
CGroupsを使用して、リソースの使用を制限し、そのような問題を防ぐことができます
実際、cgroupはより高度な制御を提供しますが、私の意見では現在、構成がより複雑です。
簡単な例を次に示します。
_$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)
_
それ:
r2(){ r2 $@$@;};r2 r2
を実行します。これは、スタックメモリを要求している間、CPUとRAMを無限に倍増することにより、指数関数的に噛み砕きます。ご覧のとおり、1GB以上をリクエストしようとすると停止しました。
_-v
_は、仮想メモリの割り当て(合計、つまり物理+スワップ)で動作することに注意してください。
仮想メモリの割り当てを制限するために、as
は_-v
_の_limits.conf
_と同等です。
私は、単一の不正なプロセスから保護するために次のことを行います。
address space limit = <physical memory> - 256MB
_。一発ギャグ:
_$ 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
_
ノート:
rss
オプションを使用しないでください。新しいカーネルでは尊重されていません。より詳細な制御を提供しますが、現在は使用がより複雑です。
memory.max_usage_in_bytes
_は、物理メモリを個別に考慮および制限できます。ulimit -m
_および/または_limits.conf
_のrss
は同様の機能を提供することを目的としていましたが、カーネルLinux 2.4.30以降は機能しません!cgroup_enable=memory swapaccount=1
_。cgm
は、公式にサポートされているユーザースペースツールのようです。例えば。現在の設定を確認するには:
_$ 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の優先順位と制限を(systemdユニットを介して)事前構成し、メモリが不足しないようにすることを期待しましょう。
あなたは押すことができるかもしれません Ctrl-z プログラムを一時停止します。次に、kill %1
(またはジョブ番号が何であれ、PIDを使用できます)を実行できます。
ulimit
コマンドを使用して、プロセスで使用可能なメモリの量を制限することができます。
CGroupsを使用して、リソースの使用を制限し、そのような問題を防ぐことができます。 https://en.wikipedia.org/wiki/Cgroups
GUIに、フォーカスのあるアプリケーションにSIGSTOPを送信するためのホットキーがあればいいのですが。
常に古典的なxkill
コマンドがあります(私のシステムのxorg-x11-apps-7.4-14.fc14.src.rpmから)。ターゲットウィンドウを強制終了する代わりにSIGSTOPを送信するクローンを作成することはそれほど難しくないはずです。