linuxにおけるメモリと関連コマンド(free, vmstat, top, sar)
linuxにおけるメモリの扱いを中心として、関連する統計情報の閲覧、監視ツールの見方についてまとめる。下に挙げた技評の2冊および学びの多かった記事を基にしています。
ページキャッシュ
free
とかtop
とかの説明に入る前に、まず、OSのキャッシュの話から始める。大規模なデータを扱う際、Linuxはキャッシュの仕組みによって効率的にメモリ管理を行うことで、ディスクへのアクセスを減らし、データアクセスを高速化している。これは「ページキャッシュ」と呼ばれる仕組みで実現している。
Linuxには仮想アドレスと呼ばれる機能を提供している。論理的なアドレス(リニアアドレス)をOSが提供することによって、各プロセスはメモリ(あるいはスワップ)の物理的なアドレスを気にすることなく扱うことができるようになる。この際、Linuxはメモリ領域をアドレス単位ではなく1つのまとまったブロックとして提供しており、その単位が「ページ」と呼ばれる。サイズは4KB。このページをOSはメモリ上にずっと確保しており、別のプロセスが再び同じデータにアクセスしようとしたときに、ディスクへのアクセスを行うことなく高速に処理できる、という仕組みが、ページキャッシュの大まかな仕組み。Linuxはメモリが空いている限り全てページキャッシュに回そうとする。
基本的にはメモリに空きがあれば全てキャッシュに乗せるが、開いていない場合は古いキャッシュから破棄して新しいキャッシュと入れ替える。sar -r
で確認すると、memused
の比率におけるkbcached
の値が確認できる。
06:00:01 AM kbmemfree kbmemused %memused kbbuffers kbcached kbswpfree kbswpused %swpused kbswpcad 06:10:01 AM 161280 3824360 95.95 6672 2008004 4174336 18620 0.44 380 06:20:01 AM 171652 3813988 95.69 18132 1995240 4174336 18620 0.44 380
メモリとディスク
メモリへのアクセスとディスクへのアクセスには、105から106(10万〜100万)倍程度の速度差が生じる。これは、メモリが電気的な部品であって、探索速度に物理的制約を受けることがないのに対して、ディスクの場合はヘッドの移動、ディスク回転という物理的な動作を伴う必要があることに起因する。を必要なデータがメモリ内に乗っていれば、多少アプリケーションが非効率であっても、ある程度パフォーマンスが担保できる。アプリケーションを構成する上で、iowaitを避けて極力全てのアクセスをメモリで行いたいのは、こうした理由からである。また、OSのキャッシュで捌ききれなくなったときに、分散の考え方が必要になる。
メモリの使用状況を確認する
メモリ使用量を計測する各種コマンドについて。環境はvagrantのubuntu14.04 LTS。
free
現在のメモリ使用量を確認できる。この出力は、/proc/meminfo
ファイルを元にしている。
オプションの-t
はTotal
行の出力、-m
はMB単位での出力を行う。
vagrant@vagrant-ubuntu-trusty-64:~$ free -tm total used free shared buffers cached Mem: 489 336 153 0 12 211 -/+ buffers/cache: 112 377 Swap: 0 0 0 Total: 489 336 153
Mem
行は、物理的なメモリの総量。489MBのメモリが存在し、336MBが既に使用され、空きメモリは153MBということが分かる。buffers
とcached
はOSによって予約されている領域。buffers
およびcache
は、メモリが不足する場合に開放して利用できるようにする。よって、実質的なメモリの使用量および利用可能量を見るためには、2行目の-/+ buffers/cache
行を見るのが正しい。2行目のused
はMem
行のused
からbuffers/cached
を引いた使用量、free
は足した量を表示している。ここではSwap
行に出力はないが、メモリに載せるデータが増えてくると、スワップ領域がディスクに作成され、一部のデータがそちらに移される。
スワップ
ディスクを利用して使用可能なメモリ領域を増やす。メモリ容量が不足している場合に、現在使われていないデータを一時的にスワップ領域に退避させてメモリを開放する。 スワップ領域に退避させたデータの参照をプロセスが要求したときに、再度メモリ上に読み込まれる。ディスクへのアクセスがあるので、もちろん遅い。スワップ領域への退避・アクセスが頻発する条件は、要改善項目。メモリが不足しているため、以下のようなことを検討する必要がある。
- 極端に大きなプロセス(メモリリークなどの異常含む)がないか
- プログラム内に非効率にメモリを使う箇所がないか
- メモリを増設できないか
- 分散を検討できないか
ボトルネックの特定には、下で挙げるvmstat
やsar
を使うとよい。
vmstat
メモリやCPUの情報だけでなく、スワップやプロセスの情報を出力できる。
vagrant@vagrant-ubuntu-trusty-64:~$ vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 3 0 0 144368 23220 200692 0 0 54 20 21 327 0 1 99 0 0 0 0 0 144360 23220 200692 0 0 0 0 32 66 0 0 100 0 0 0 0 0 144360 23220 200692 0 0 0 0 24 52 0 0 100 0 0
si
(スワップイン), so
(スワップアウト)が頻繁に動いている場合はスワップが発生している。他の項目としては、r
は実行待ち状態のプロセス数、b
は割り込み不可能なスリープ状態にあるプロセス数。memory
の項目はfree
と同様、io
はデバイスとのブロックの転送量、system
はコンテキストの毎秒の切り替えレート(割り込み回数・コンテキストスイッチの回数)、cpu
はCPU使用率である。
top
topコマンドは、現在のシステム全体の負荷情報を閲覧するのに利用する。プロセス・CPU・メモリ・スワップが確認できる。主なオプションは、以下の通り。
vagrant@vagrant-ubuntu-trusty-64:~$ top # CPU使用率順にソート vagrant@vagrant-ubuntu-trusty-64:~$ top -o %MEM # メモリ使用率順にソート. -o fieldnameでソート順を切り替えられる。centosでは-a? vagrant@vagrant-ubuntu-trusty-64:~$ top -p [PID] # 特定のプロセスを監視 vagrant@vagrant-ubuntu-trusty-64:~$ top -d3 # 3秒ごとに更新
topではshift
でソート順の切り替えができる。
shift + m // メモリ使用率順 shift + p // CPU使用率順
ヘッダについて
vagrant@vagrant-ubuntu-trusty-64:~$ top top - 19:56:06 up 2:12, 2 users, load average: 0.00, 0.01, 0.05 Tasks: 75 total, 1 running, 74 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 501748 total, 140316 used, 361432 free, 5252 buffers KiB Swap: 0 total, 0 used, 0 free. 24128 cached Mem
1行目は、uptime
コマンドと同じ出力。現在時刻、システム稼働時間、ログインユーザ数、LoadAverageと並ぶ。LAは左から、1分、5分、15分を単位時間としている。2行目は、タスクの統計。上の例では、75のタスクがあり、稼働中のものは1、待機中のものが74となっている。3行目はCPU。us
がユーザ、sy
がシステム、ni
がnice、id
がidle、wa
がiowait、hi
はhardware interrupt、si
はsoftware interrupt、st
がsteal。
3行目、4行目はメモリ統計。これはfree
で解説したものと同じ。
プロセス一覧
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1789 vagrant 20 0 107696 1352 348 S 0.3 0.3 0:01.28 sshd 8523 vagrant 20 0 23536 1560 1116 R 0.3 0.3 0:00.02 top 1 root 20 0 33608 1716 276 S 0.0 0.3 0:00.86 init
ここでのCPUは1コアを100%とした値が出力されるため、仮に何かのバッチスクリプトのプロセスが100%になっていたからといって焦る必要はない(効率はよくないだろうけど)。
PID // プロセスid USER // 実行ユーザ PR // 優先度 NI // ナイス値 VIRT // 割り当てられた仮想メモリのサイズ RES // スワップのない物理メモリのサイズ SHR // 割り当てられた共有メモリのサイズ S // プロセスのステータス。R: 実行可能,S: 停止,D: 割り込み不可の停止,T: 停止またはトレース中,Z: ゾンビ・プロセス,W: スワップ・アウトしたプロセス, N: ナイス値が正 %CPU // CPU使用率 %MEM // メモリ使用率 TIME // プロセスの経過時間 COMMAND // タスクのコマンド名
LoadAverage
1CPUにおける単位時間あたりの実行待ち、ディスクI/Oの完了待ちをしているタスク。これが高ければ高いほどCPUかIO起因で高負荷といえる。雑な例えをすると、手元のPCでchromeとfirefoxとxcodeを立ち上げて更にでかいExcelファイル読み込もうとすると、マルチタスクとはいえちょっと重いよねって話。
sar
sarコマンドは、CPU使用率およびディスクI/Oを出力できる。他のコマンドと異なる点としては、過去に遡れることが挙げられる。また、topやfreeと異なり定期的に1行ずつ出力されるので、負荷試験時などに計測を行いやすい。sysstat
パッケージをインストールする必要があるので、sarコマンドがない場合はインストールする。
vagrant@vagrant-ubuntu-trusty-64:~$ sudo apt-get install sysstat
デフォルトでは10分間隔でログ出力されている。必要に応じて変更する場合は、以下のファイルを編集する。また、ログの保存期間も必要に応じて伸ばしておく。centosであれば/etc/sysconfig/sysstat
あたり。ubuntuであれば/etc/default/sysstat
?(未検証)
vagrant@vagrant-ubuntu-trusty-64:~$ cat /etc/cron.d/sysstat ~ # Activity reports every 10 minutes everyday 5-55/10 * * * * root command -v debian-sa1 > /dev/null && debian-sa1 1 1
オプション
vagrant@vagrant-ubuntu-trusty-64:~$ sar -q loadaverage vagrant@vagrant-ubuntu-trusty-64:~$ sar -u CPU使用率 vagrant@vagrant-ubuntu-trusty-64:~$ sar -b I/O vagrant@vagrant-ubuntu-trusty-64:~$ sar -r メモリとスワップ使用率 vagrant@vagrant-ubuntu-trusty-64:~$ sar -s time 時間以降のデータ vagrant@vagrant-ubuntu-trusty-64:~$ sar -e time 時間までのデータ
オプションなしでsar 1 5
等の指定も可能。この場合は、1秒を単位時間として5秒間CPUの使用率を出力する。
vagrant@vagrant-ubuntu-trusty-64:~$ sar 1 5 Linux 3.13.0-55-generic (vagrant-ubuntu-trusty-64) 07/06/2015 _x86_64_ (1 CPU) 08:47:12 PM CPU %user %nice %system %iowait %steal %idle 08:47:13 PM all 0.99 0.00 0.00 0.00 0.00 99.01 08:47:14 PM all 0.00 0.00 0.00 0.00 0.00 100.00 08:47:15 PM all 0.00 0.00 1.00 0.00 0.00 99.00 08:47:16 PM all 0.00 0.00 0.00 0.00 0.00 100.00 08:47:17 PM all 0.00 0.00 0.00 0.00 0.00 100.00 Average: all 0.20 0.00 0.20 0.00 0.00 99.60
sar
は過去に遡って出力できるため、ボトルネックの特定に重宝する。-q
でLoadAverageが高かった場合は、-u -e
で該当時間帯のCPU使用率をチェック、user
が高ければCPU負荷、iowait
が高ければディスクI/O負荷と切り分けることができる。
vagrant@vagrant-ubuntu-trusty-64:~$ sar -u -s 04:00:00 04:00:01 AM CPU %user %nice %system %iowait %steal %idle 04:10:01 AM all 4.78 0.01 1.38 2.84 0.00 90.99 04:20:01 AM all 3.03 0.00 1.10 0.02 0.00 95.85 04:30:01 AM all 2.99 0.00 1.06 0.02 0.00 95.93
監視ツールの見方
まず、監視ツールを導入する。ここではXymon
(旧hobbit
)を利用して、メモリに関する部分のみ見ていくことにする。Xymon
はオープンソースのネットワーク・サーバ監視ツール。読み方はサイモンorシモン。恐らくサイモンだろう。シモンとガーファンクルとは言わないし。。。GPL2ライセンス。
これが監視ツールで満たときのメモリ使用率。
free
コマンドを元にグラフを出力している。
actual
は、バッファとキャッシュ分を差し引いた値。free
でいうところの-/+ buffers/cache
行のused
のことである。real
は、Mem
行、つまりバッファとキャッシュを含めた使用率の値である。そのため、real
よりもactual
の方が低い値となっている。ページキャッシュがあまり乗っていない起動直後は、actual
とreal
に大きな変化が見られない。swap
はその名の通りスワップです。
言い回しが違うだけで確信が掴めなかったけど、以下のMLに書いてあった。
インストール手順は、こちらの記事が参考になります。
おわり
Linuxにおけるメモリの扱いを中心としてざっと見てきたが(CPUとかディスクとかが中途半端に入ったけど)、メモリ管理の仕組みそのものや、メモリ管理を意識したスケールアウト時の考え方、各コマンドの詳細、実践に則した使い方、監視ツールの多項目等、もっと掘り下げたいところ。間違い等あれば指摘ください。