銀色うつ時間

思い出すたび何か胸につっかえてるだけ

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ファイルを元にしている。 オプションの-tTotal行の出力、-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ということが分かる。bufferscachedはOSによって予約されている領域。buffersおよびcacheは、メモリが不足する場合に開放して利用できるようにする。よって、実質的なメモリの使用量および利用可能量を見るためには、2行目の-/+ buffers/cache行を見るのが正しい。2行目のusedMem行のusedからbuffers/cachedを引いた使用量、freeは足した量を表示している。ここではSwap行に出力はないが、メモリに載せるデータが増えてくると、スワップ領域がディスクに作成され、一部のデータがそちらに移される。

スワップ

ディスクを利用して使用可能なメモリ領域を増やす。メモリ容量が不足している場合に、現在使われていないデータを一時的にスワップ領域に退避させてメモリを開放する。 スワップ領域に退避させたデータの参照をプロセスが要求したときに、再度メモリ上に読み込まれる。ディスクへのアクセスがあるので、もちろん遅い。スワップ領域への退避・アクセスが頻発する条件は、要改善項目。メモリが不足しているため、以下のようなことを検討する必要がある。

  • 極端に大きなプロセス(メモリリークなどの異常含む)がないか
  • プログラム内に非効率にメモリを使う箇所がないか
  • メモリを増設できないか
  • 分散を検討できないか

ボトルネックの特定には、下で挙げるvmstatsarを使うとよい。

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はコンテキストの毎秒の切り替えレート(割り込み回数・コンテキストスイッチの回数)、cpuCPU使用率である。

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でchromefirefoxxcodeを立ち上げて更にでかい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ライセンス。

これが監視ツールで満たときのメモリ使用率。

f:id:sisidovski:20150707060345p:plain

freeコマンドを元にグラフを出力している。

actualは、バッファとキャッシュ分を差し引いた値。freeでいうところの-/+ buffers/cache行のusedのことである。realは、Mem行、つまりバッファとキャッシュを含めた使用率の値である。そのため、realよりもactualの方が低い値となっている。ページキャッシュがあまり乗っていない起動直後は、actualrealに大きな変化が見られない。swapはその名の通りスワップです。

言い回しが違うだけで確信が掴めなかったけど、以下のMLに書いてあった。

Re: [hobbit] Memory check

インストール手順は、こちらの記事が参考になります。

karia.hatenablog.jp

おわり

Linuxにおけるメモリの扱いを中心としてざっと見てきたが(CPUとかディスクとかが中途半端に入ったけど)、メモリ管理の仕組みそのものや、メモリ管理を意識したスケールアウト時の考え方、各コマンドの詳細、実践に則した使い方、監視ツールの多項目等、もっと掘り下げたいところ。間違い等あれば指摘ください。

参考資料