暴走してどんどんメモリを食うスクリプトが OS全体のメモリ使用量(CentOS5 ... カーネルは2.6系になる)の動作にどんな影響を与えるのか ってのを見るために以下のようなテストをしてみました。仕組みはだいたい理解してるけど、細かい数値を追ったことはなかったのでやってみました。
# 1秒ごとに5MB単位でメモリを食うプロセス # 数値はお好みで perl -e "while(1){ sleep 1; push @h , 1 x 1024 x 1024 x 5 } "
ちなみにtopで見張るときは
- メモリ使用量でソートされるようにして
- top起動中に shift + o を押して n を押すと 実メモリ使用量でソートされる
- 更新時間を短くする
- top 起動中に d を押して、秒数を指定する。今回は1秒で
- top -d1 でもいいみたい(追記)
- ついでに色を付けておく
- top起動中にB もしくは z を押す / x を押すとソートしているカラムの色だけが反転表示
という設定にしておくと数値が見やすいと思います。自分の設定では画像のようになりました。赤いなぁ
さて以上のような条件で実際に実行してみると Perlのプロセスが1秒ごとに5MBずつメモリを食っていく様子が分かるのですが、注目してみておくべき数値は、Perlのプロセスのメモリ使用率と、メモリ/ スワップ使用量の統計だと思います。1秒ごとに数値が変化するのですが、ただ単純に数値が増えていく というわけではなくて、あっちがふえたりこっちが減ったりとなかなか興味深い動きをします。以下、topのスナップショットを貼っていきます。
( 実際にご自身の環境で試して目で追ってもらった方が分かりやすいと思いますが....あと、メモリの総計を追うだけならvmstatの方がいいですね)
# 初期値 # Perlのメモリ食いプロセスはまだ動いていません top - 07:58:48 up 7 min, 2 users, load average: 0.10, 0.21, 0.11 Mem: 255768k total, 122604k used, 133164k free, 7932k buffers Swap: 524280k total, 0k used, 524280k free, 81424k cached
# Mem: usedが若干増えて、freeが若干減る #perlのプロセスがソートの上位にあがってくる top - 07:58:53 up 7 min, 2 users, load average: 0.09, 0.21, 0.11 Mem: 255768k total, 135536k used, 120232k free, 7992k buffers Swap: 524280k total, 0k used, 524280k free, 82688k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1979 root 18 0 14888 12m 1032 S 4.6 4.9 0:00.07 perl
# Mem: totalが Mem:usedとほぼ同値になった ( Mem: freeがかなり減少 ) # PerlのRES(実メモリ使用量) が 127MB。 %MEMは51.0 # ここからbuffersとcachedが減少し始める top - 07:59:17 up 8 min, 3 users, load average: 0.07, 0.20, 0.10 Mem: 255768k total, 252228k used, 3540k free, 7856k buffers Swap: 524280k total, 0k used, 524280k free, 79792k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1979 root 18 0 129m 127m 1032 S 4.5 51.0 0:00.81 perl
# Mem:usedはほとんど動かない # buffers/cachedがどんどん減っている top - 07:59:27 up 8 min, 3 users, load average: 0.21, 0.22, 0.11 Mem: 255768k total, 252756k used, 3012k free, 348k buffers Swap: 524280k total, 80k used, 524200k free, 36664k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1979 root 18 0 179m 177m 1032 S 4.6 71.0 0:01.10 perl
# cachedが食い尽くされて、Swap: used が増加し始める # この時点からPerlの VIRT(実メモリ+スワップ)の値がRES(実メモリのサイズ)と大きく差をつけるようになる top - 07:59:37 up 8 min, 3 users, load average: 0.28, 0.24, 0.12 Mem: 255768k total, 251672k used, 4096k free, 60k buffers Swap: 524280k total, 14144k used, 510136k free, 5976k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1979 root 18 0 219m 207m 580 S 4.4 82.9 0:01.43 perl
# プロセス肥大中 / Swapのusedが大きくなってる top - 08:01:25 up 10 min, 3 users, load average: 1.96, 0.66, 0.27 Mem: 255768k total, 248980k used, 6788k free, 404k buffers Swap: 524280k total, 415600k used, 108680k free, 7540k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1979 root 18 0 569m 179m 268 R 2.8 71.8 0:03.91 perl
# スワップのfreeが0に!!!!! # PerlのVIRT(実メモリ+スワップ) が725MB。 # メモリが枯渇状態MAX top - 08:02:04 up 11 min, 3 users, load average: 1.70, 0.70, 0.29 Mem: 255768k total, 251892k used, 3876k free, 68k buffers Swap: 524280k total, 524280k used, 0k free, 1812k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1979 root 18 0 725m 232m 276 S 3.4 93.1 0:05.19 perl
#Swapも食い尽くしてしまうと急にMem: free/Swap:freeの値が増えます。 #Perlのメモリバカ食いプロセスは消えています。 #Perlのワンライナーを起動したsshの画面を見ると「Out of memory!」という文字が出てします。 #これが噂のOOM-Killerですね。と言っても今回初めて見ました。 top - 08:02:05 up 11 min, 3 users, load average: 1.70, 0.70, 0.29 Mem: 255768k total, 15492k used, 240276k free, 120k buffers Swap: 524280k total, 22952k used, 501328k free, 3380k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 85 root 10 -5 0 0 0 S 0.6 0.0 0:00.70 kswapd0
プロセスが肥大化してメモリを食いきってしまうとカーネルがOOM Killerなる機構を呼び出して肥大したプロセスをkillする( SIGEMT を送る) ようです。以下、ググってでてきたページから引用して載せておきます。
http://wiki.livedoor.jp/linuxfs/d/OOMkiller Linux kernelがメモリ不足(swapも含め)に陥ったとき、このOOM Killerが発動し、縦横無尽にプロセスを駆逐していきます。その際、無差別ともとれる残虐な行為から悪名高いメモリ不足解決器 (OOM killer) と揶揄されて今日に至ります。
メモリが枯渇した状態でOOM Killerが呼び出されるので、OOM Killer自体はメモリをほとんど割り当てないような実装になってるって どこかで読んで、なるほどー!と思ったんですけど どこだったか忘れてしまいました。
ちなみにOOM Killerが呼び出された詳細は /var/log/message 以下にログがとられています。
なんとなく思いつきでやったテストでしたが、カーネルがメモリを操る様子が逐一見て取れたので非常にためになりました。OOM Killer が起動するタイミングも確認することが出来たし。( topの更新時間を0.01秒単位で指定するとさらにダイナミックな変化が追えます)
他に見るべきポイントがあったらつっこみ待ちです