サーバ負荷を確認する方法

# はじめに
名著、[サーバ/インフラを支える技術](http://www.amazon.co.jp/24%E6%99%82%E9%96%93365%E6%97%A5-%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-%E2%80%BE%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%A9%E3%83%93%E3%83%AA%E3%83%86%E3%82%A3%E3%80%81%E3%83%8F%E3%82%A4%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9%E3%80%81%E7%9C%81%E5%8A%9B%E9%81%8B%E7%94%A8-PRESS-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA/dp/4774135666)を何度か読んでいるが、まだまだ理解が浅い部分が多い。そこで再度読み込むと共に、4章の一部についてまとめてみた

# ロードアベレージを見る
## ロードアベレージとは
単位時間あたりに待たされたタスク数。ロードアベレージが高い=平均して待たされたタスク数が多い、つまり負荷が高い

## タスクの状態
カーネル内部の実行処理の単位はプロセスである。なので、ここではプロセスの状態と読み替える。(この辺適当だがすみません)

| 状態 | 説明 | 詳細 |
|:-----------|:------------|:-------------|
| TASK_RUNNING         | 実行可能状態            |CPUが空けばすぐに実行できる
| TASK_INTERRUPTIBLE   | 割り込み可能な待ち状態   |復帰時間が予測不可能な長時間の待ち状態。スリープやユーザー入力等。
| TASK_UNINTERRUPTIBLE | 割り込み不可能な待ち状態 |短時間で復帰する待ち状態。I/O待ち等。
| TASK_STOPPED         | 実行中断状態            |
| TASK_ZOMBIE          | ゾンビ状態              |

このうち、ロードアベレージに計上されるのはTASK_RUNNNINGとTASK_UNINTERRUPTIBLEの2つである。

## どうやってみるか
topやuptimeを使う

###top
```
Processes: 210 total, 3 running, 12 stuck, 195 sleeping, 1313 threads                                                                                                                                                                04:58:24
Load Avg: 4.89, 4.00, 3.75  CPU usage: 10.14% user, 9.17% sys, 80.67% idle   SharedLibs: 11M resident, 6396K data, 0B linkedit. MemRegions: 105873 total, 2311M resident, 38M private, 440M shared.
```
Load Avgの欄に表示される。左から順に、1分、5分、15分の値。


###uptime
```
$ uptime
 5:12  up 11 days,  4:01, 2 users, load averages: 2.74 3.00 3.41
```
左から順に、現在時刻、ログイン時間、ログインユーザー数、ロードアベレージ。
まさにロードアベレージを見るためにあるようなコマンド。

# CPUとI/Oのどちらがボトルネックか探る
ロードアベレージが高かったら、cpuバウンドなのかI/Oバウンドなのか探る。(注 hogeバウンド・・・hogeがボトルネックとなっているような処理)

### cpu負荷が高い状態とは
大規模な計算をするプログラムの場合、ディスクの入出力が行わないが処理に時間を要する。この場合cpu負荷が高い処理。

### I/O負荷が高い状態とは
ディスクに保存されたデータを大量に読み書きするような処理は、I/O負荷が高い処理。

##どうやってみるか
psやsarやvmstatを使う

###sar
過去にさかのぼってサーバーの統計情報を見ることができる。

```
$ sar

00時00分01秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
00時10分01秒     all      0.00      0.00      0.02      0.00      0.00     99.97
00時20分01秒     all      0.00      0.00      0.03      0.00      0.00     99.97
00時30分01秒     all      0.00      0.00      0.02      0.00      0.00     99.98
00時40分01秒     all      0.00      0.00      0.02      0.00      0.00     99.98
00時50分01秒     all      0.00      0.00      0.03      0.00      0.00     99.96
01時00分01秒     all      0.00      0.00      0.03      0.00      0.00     99.97
01時10分01秒     all      0.00      0.00      0.03      0.00      0.00     99.96
01時20分02秒     all      0.00      0.00      0.02      0.00      0.00     99.97
01時30分01秒     all      0.00      0.00      0.02      0.00      0.00     99.97
01時40分01秒     all      0.00      0.00      0.02      0.00      0.00     99.97
01時50分01秒     all      0.00      0.00      0.02      0.00      0.00     99.97
02時00分01秒     all      0.00      0.00      0.02      0.00      0.00     99.97
```

+ %user：ユーザーモードでcpuが使用された時間の割合
+ %system：システムモードでcpuが使用された時間の割合
+ %iowait：I/O待ちの時間の割合

現在の情報も見ることができる
`sar 繰り返し間隔(秒) 繰り返し回数`

```
$ sar 2 5

05時34分19秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
05時34分21秒     all      5.57      0.00      1.74      0.00      0.35     92.33
05時34分23秒     all      6.27      0.00      1.39      0.00      0.00     92.33
05時34分25秒     all      6.55      0.00      2.41      0.00      0.00     91.03
05時34分27秒     all      4.79      0.00      1.71      0.00      0.34     93.15
05時34分29秒     all      5.65      0.00      0.71      0.00      0.00     93.64
平均値:      all      5.77      0.00      1.60      0.00      0.14     92.49
```

####-qでロードアベレージを見ることができる

```
$ sar -q

00時00分01秒   runq-sz  plist-sz   ldavg-1   ldavg-5  ldavg-15
00時10分01秒         0        99      0.11      0.05      0.00
00時20分01秒         0        99      0.00      0.00      0.00
00時30分01秒         0        99      0.00      0.00      0.00
00時40分01秒         0        99      0.00      0.00      0.00
```
####-rでメモリ利用状況を見ることができる

```
$ sar -r

00時00分01秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit
00時10分01秒    359292    660772     64.78    191008    361304     67436      2.16
00時20分01秒    359292    660772     64.78    191008    361308     67436      2.16
00時30分01秒    359152    660912     64.79    191008    361308     67436      2.16
00時40分01秒    359168    660896     64.79    191008    361312     67436      2.16
00時50分01秒    359152    660912     64.79    191008    361312     67436      2.16

```

kbmemfree：物理メモリの空き容量
kbmemused：物理メモリの使用量
%memused：物理メモリ使用率
kbbuffers：カーネル内のバッファとして使用されている物理メモリの容量
kbcached：カーネル内でキャッシュ用メモリとして使用されている物理メモリの容量
kbcommit

####-Sでswapの状態に関して見ることができる

```
$ sar -S

00時00分01秒 kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
00時10分01秒   2097148         0      0.00         0      0.00
00時20分01秒   2097148         0      0.00         0      0.00
00時30分01秒   2097148         0      0.00         0      0.00
00時40分01秒   2097148         0      0.00         0      0.00
```
kbswpfree：スワップ領域の空き容量
kbswpused：スワップ領域の使用容量
%swpused：スワップ領域の使用量割合
kbswpcad：スワップ領域のキャッシュ容量。
>Amount  of  cached  swap memory in kilobytes.  This is memory that once was swapped out, is swapped back in but still also is in the swap area (if memory is needed it doesn’t need to be swapped
                     out again because it is already in the swap area. This saves I/O).

スワップしたデータが戻る際にキャッシュしておくメモリの存在の事らしい。そのデータが再度スワップした時に、キャッシュを使う事でディスクI/Oを抑えられる利点がある。
スワップ=ディスクへの書き込みなので、2度以上スワップが発生する場合はキャッシュを使って効率よくしているのかな。

%swpcad：スワップ領域の使用量に対するスワップ領域のキャッシュ量

####-Wでスワップ発生状況を見ることができる

```
$ sar -W

00時00分01秒  pswpin/s pswpout/s
00時10分01秒      0.00      0.00
00時20分01秒      0.00      0.00
00時30分01秒      0.00      0.00
00時40分01秒      0.00      0.00
```

pswpin：1秒間にスワップインしてる回数
pswpout：1秒間にスワップアウトしてる回数

###ps
プロセスの統計情報を見ることができる

```
$ ps auwx | head
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  19232  1516 ?        Ss   Feb09   0:00 /sbin/init
root         2  0.0  0.0      0     0 ?        S    Feb09   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    Feb09   0:00 [migration/0]
root         4  0.0  0.0      0     0 ?        S    Feb09   0:00 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S    Feb09   0:00 [stopper/0]
root         6  0.0  0.0      0     0 ?        S    Feb09   0:06 [watchdog/0]
root         7  0.0  0.0      0     0 ?        S    Feb09   0:00 [migration/1]
root         8  0.0  0.0      0     0 ?        S    Feb09   0:00 [stopper/1]
root         9  0.0  0.0      0     0 ?        S    Feb09   0:00 [ksoftirqd/1]
```

%CPU：そのコマンドのCPU使用率
%MEM：プロセスの物理メモリ消費率
VSZ：Virtual Set Size。そのプロセスが確保している仮想メモリサイズ
RSS：Resident Set Size。そのプロセスが確保している物理メモリサイズ
STAT：プロセスの状態

####STATについてもう少し詳しく
先に説明したタスクの状態と、下記のように対応する
R：TASK_RUNNING
S:TASK_INTERRUPTIBLE
D:TASK_UNINTERRUPTIBLE
Z:TASK_ZOMBIE

####物理メモリと仮想メモリについて
カーネルはプロセスに対して、割り当てたメモリのアドレスを渡す際に、仮想的なメモリのアドレスを渡す。そしてプロセスがメモリに対して初めて書き込みを行った時点で、物理メモリへの割り当てが発生する(Copy on Write)。
その際物理メモリが足りないと、長時間使用されていない領域の物理メモリと仮想メモリの割り当てを解除し、解除された物理メモリの内容はディスクに退避させられる。その状態をswapという。

###vmstat
仮想メモリの状態について調べることができる

```
[vpsuser@ik1-340-30292 ~]$ vmstat
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 350568 191048 362408    0    0     0     0    3    5  0  0 100  0  0
```

以下、man vmstatからのコピペ

>   Procs
       r: ランタイム待ちのプロセス数
       b: 割り込み不可能なスリープ状態にあるプロセス数

>   Memory
       swpd: 仮想メモリの量。
       free: 空きメモリの量。
       buff: バッファに用いられているメモリの量。
       cache: キャッシュに用いられているメモリの量。
       inact: アクティブでないメモリの量 (-a オプション)。
       active: アクティブなメモリの量 (-a オプション)。

>   Swap
       si: ディスクからスワップインされているメモリの量 (/s)。
       so: ディスクにスワップしているメモリの量 (/s)。

>   IO
       bi: ブロックデバイスから受け取ったブロック (blocks/s)。
       bo: ブロックデバイスに送られたブロック (blocks/s)。

>   System
       in: 一秒あたりの割り込み回数。クロック割り込みも含む。
       cs: 一秒あたりのコンテキストスイッチの回数。

>   CPU
       これらは CPU の総時間に対するパーセンテージである。
       us: カーネルコード以外の実行に使用した時間 (ユーザー時間、nice 時間を含む)。
       sy: カーネルコードの実行に使用した時間 (システム時間)。
       id: アイドル時間。Linux 2.5.41 以前では、IO 待ち時間を含んでいる。
       wa: IO 待ち時間。Linux 2.5.41 以前では、0 と表示される。
       st: 仮想マシンから盗まれた時間。Linux 2.6.11より前では未知。