綾小路龍之介の素人思考

[linux] 空きメモリ確認はvmstatのfreeではなくfreeの-/+ buffers/cacheのfree

firefoxを常時起動させておくと、vmstatのfreeがどんどん消費されていく。それにしては、topコマンドのVIRTはほとんど変化無し。これ一体どういうこと?空きメモリの定義って何?結局、アプリケーションがアロケートできるメモリの総計は「空きメモリ+バッファキャッシュ+ページキャッシュ」これを表示するのが「freeの-/+buffers/cacheのfree」。vmstatでは表示されないけれど、それぞれの情報が別々に表示されるので、足し算すれば問題なし。せっかく計算機使っているのに手計算したいと言うのなら話は別だ。

freeとvmstatの両方でfreeをチェックする。両方の出力でfreeの定義が違っている様子。freeコマンドMem項目のfreeは空きメモリ、bufferはバッファキャッシュ、chachedはページキャッシュ、空きメモリとバッファキャッシュとページキャッシュの和が-/+ buffers/cacheのfree。Linuxは起動中に空きメモリから割り当てたメモリをメモリ使用後にすぐに開放するのではなく、キャッシュ(バッファキャッシュ、ページキャッシュ)に蓄えておき、再利用できるようにしている。キャッシュは「効率化」のためのもので、空きメモリを越えるサイズのメモリアロケーションが行われた場合には不足分をキャッシュから割り当てられる。つまり、アプリケーションがアロケーション可能なメモリサイズは空きメモリ+バッファキャッシュ+ページキャッシュ。これを表しているのがfreeの-/+ buffers/cacheのfree。計算が面倒でなければ、vmstatのfreeとbuffとcacheを足し算すればよい。

$ free
             total       used       free     shared    buffers     cached
Mem:       1035792     984852      50940          0     256344     375956
-/+ buffers/cache:     352552     683240
Swap:       489940          0     489940
$ vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 5  0      0  51292 256352 375956    0    0     0     0    1    0 97  0  3  0

cronに仕込んで1時間に1回の定点観測。両方のコマンドにはdelayを指定してポーリングする機能がある。vmstatに関してはメモリに関する情報が瞬間のモノだということなので自前のポーリングでもcronでも変わらないはず。freeについては不明。

$ crontab -l
# m h  dom mon dow   command
0 * * * * vmstat | tail -n 1 >> vmstat.dat
0 * * * * free | tail -n 3 | sed 's/^.*:\s*//' | tr '\n' ' ' | sed 's/$/\n/' >> free.dat

出来たログファイルは以下のような感じ。vmstatの方はヘッダー部分を削除したもの。freeの方は項目名を削除して数値だけを1行にまとめたもの。

$ tail vmstat.dat
tail vmstat.dat
 5  0      0  53068 256288 375928    0    0     0     0    1    0 97  0  3  0
 9  0      0  52240 256296 375936    0    0     0     0    1    0 97  0  3  0
 9  0      0  53396 256300 375936    0    0     0     0    1    0 97  0  3  0
 7  0      0  53288 256300 375944    0    0     0     0    1    0 97  0  3  0
10  0      0  52972 256308 375944    0    0     0     0    1    0 97  0  3  0
 7  0      0  52608 256312 375948    0    0     0     0    1    0 97  0  3  0
 6  2      0  52120 256312 375948    0    0     0     0    1    0 97  0  3  0
11  1      0  52464 256312 375944    0    0     0     0    1    0 97  0  3  0
 7  0      0  52744 256312 375944    0    0     0     0    1    0 97  0  3  0
 8  0      0  52072 256312 375944    0    0     0     0    1    0 97  0  3  0
$ tail free.dat
1035792     982624      53168          0     256284     375932 350408     685384 489940          0     489940
1035792     983552      52240          0     256296     375936 351320     684472 489940          0     489940
1035792     982396      53396          0     256300     375936 350160     685632 489940          0     489940
1035792     982504      53288          0     256300     375944 350260     685532 489940          0     489940
1035792     982620      53172          0     256308     375944 350368     685424 489940          0     489940
1035792     982584      53208          0     256312     375948 350324     685468 489940          0     489940
1035792     983472      52320          0     256312     375948 351212     684580 489940          0     489940
1035792     982640      53152          0     256312     375944 350384     685408 489940          0     489940
1035792     982948      52844          0     256312     375944 350692     685100 489940          0     489940
1035792     983220      52572          0     256312     375944 350964     684828 489940          0     489940

得られたログファイルをプロットしてみる。

$ cat vmstat.plot
#!/usr/bin/gnuplot
set term svg
set output "vmstat.svg"
set xlabel "times [hour]"
set ylabel "(free, buff, cache) bytes [MB]"
set y2label "(free+buff+cache) bytes [MB]"
set y2range [:]
set ytics nomirror
set y2tics
set key left bottom
plot "vmstat.dat" using 0:($4/1000) title "free",\
        '' using 0:($5/1000) title "buff",\
        '' using 0:($6/1000) title "cache",\
        '' using 0:(($6+$5+$4)/1000) axis x1y2 title "free+cache+buff"
$ gnuplot < vmstat.plt

vmstatのログをプロットした結果が以下。空きメモリだけに注目すると、50MBでメモリ不足かもしれないと思ってしまうかもしれないけれど、アロケーション可能なメモリに注目すると、680MBでメモリは十分に余っていることがわかる。

このままでは、vmstatのメモリに関する情報もディスクアクセスに関する情報も瞬間の情報になるので、あまりよろしくない。vmstatにはメモリに関する情報以外をある時間間隔の平均値として出力するオプションがあるので、それを使う。ただし、これを用いた場合、vmstatが終了しなくなるので、cronに書いておくと呼び出された回数だけ、プロセスが起動してしまう。これを防ぐために、二重起動を制御する部分を加えたシェルスクリプトにして、これをcronから呼び出すようにする。cronを使って1時間に1回0分のときに起動チェック。起動しているかしていないかの基準は/tmp以下につくったシンボリックリンク(シンボリックリンクってアトミックだっけ?)。起動していた場合は何もせずにシェルスクリプト終了。起動していない場合は目的のvmstatを走らせて終了待ち状態に移行。cronから起動された際には子プロセスの終了を待たずに起動したシェルを正常終了させたいので、起動したシェルの標準出力とエラー出力を閉じておくためのおまじない"> /dev/null 2>&1 &"を付け加えておく。

$ cat vmstat.sh
sem="/tmp/checkvmstat"
ln -s /dummy $sem || exit
trap "rm $sem; exit" 2 3 15

nohup nice vmstat -n 3600 >> vmstat_.dat

rm "$sem"

exit
$ crontab -l
# m h  dom mon dow   command
#0 * * * * vmstat | tail -n 1 >> vmstat.dat
0 * * * * free | tail -n 3 | sed 's/^.*:\s*//' | tr '\n' ' ' | sed 's/$/\n/' >> free.dat
0 * * * * sh ~/vmstat.sh > /dev/null 2>&1 &

リファレンス

  1. Linux のメモリー管理(メモリ-が足りない?,メモリーリークの検出/防止)(Kodama's tips page)
  2. The Linux Kernel: メモリ管理
  3. Linuxのバッファキャッシュとページキャッシュ - 気楽に一生懸命
  4. 4.メモリ使用率(第5章 パフォーマンス管理~上級:基本管理コースII)
  5. Linuxサーバ運用マニュアル
  6. linux バッファ キャッシュ メモリ - Google 検索
  7. Manpage of FREE
  8. free manpage - Google 検索
  9. Manpage of VMSTAT
  10. vmstat 平均 - Google 検索
  11. Linuxで空きメモリ容量の調べ方: sanonosa システム管理コラム集
  12. linux メモリ top - Google 検索
  13. シェルスクリプトで正しい二重起動チェックを解説しているページ、もしくは方法を教えてください。 - 人力検索はてな
  14. 多重起動を禁止するシェルスクリプト
  15. "二重起動"|"多重起動"|"2重起動" |"排他処理" シェルスクリプト - Google 検索
  16. Debian(etch) に関する覚書
  17. defunct cron - Google 検索

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2009-05-09T19:15:22+09:00
  2. Modified: 2009-05-09T19:15:22+09:00
  3. Generated: 2017-10-01T23:09:15+09:00