topコマンドでCPU使用率を見る時の注意

LinuxサーバのCPU使用率を見たい時にtopコマンドをよく使うが、使う上で気を付けないといけないのが、タイミングによっては表示されるCPU使用率がユーザの期待するものとは異なるということ。

# サマリ情報のCPU行
topコマンドを実行するとCPUやメモリ使用率のサマリ情報がヘッダとして表示されるが、最初に表示されるCPU使用率はOSを起動してからの平均値なので、無風状態が長いほど低い数値が出る。
なお、vmstatで表示されるCPU使用率も同じ仕様なので、パフォーマンス調査などの際には最初の表示は見ない方がいい。

以下はvmstatのmanの一部
> vmstat reports information about processes, memory, paging, block IO, traps, and cpu activity.
The first report produced gives averages since the last reboot.

# %CPU列の仕様
manでtopコマンドを引くとカラムの説明として以下の記載がある。
> k: %CPU  --  CPU usage
The  task's  share  of  the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time.

したがって、%CPU列は前回のスクリーン更新からのタスクのCPU時間占有率を表す。
前回topコマンドを実行してからCPU使用率がほぼ0%で、急激に100%近くになった状態でtopコマンドを実行しても、直後に表示されるCPU使用率は100%には遠く及ばないことになる。

# 実際に試してみる

超簡単なCPU負荷スクリプトを作った。見ての通り60秒スリープした後に無限ループする。

```bash
$ cat cpuload.pl
#!/usr/bin/perl

sleep 60;
while(1){
}
```

スクリプト実行後、topコマンドでCPU使用率を見てみる。
※サーバはAWSのt2.microなので1コア

```bash
$ ./cpuload.pl &
[1] 4801
$
$ top -p 4801 -d 60 -b -n 2 ; top -p 4801 -b -n 1
top - 10:00:56 up  7:42,  2 users,  load average: 0.02, 0.22, 0.19
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
Cpu(s):  4.0%us,  0.2%sy,  0.0%ni, 95.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1017324k total,   339368k used,   677956k free,    15868k buffers
Swap:        0k total,        0k used,        0k free,   252192k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 4801 ec2-user  20   0  126m 3564 3248 S  0.0  0.4   0:00.00 cpuload.pl


top - 10:01:56 up  7:43,  2 users,  load average: 0.16, 0.21, 0.18
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
Cpu(s): 17.6%us,  0.0%sy,  0.0%ni, 82.4%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1017324k total,   339864k used,   677460k free,    15880k buffers
Swap:        0k total,        0k used,        0k free,   252196k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 4801 ec2-user  20   0  126m 3564 3248 R 17.5  0.4   0:10.53 cpuload.pl

top - 10:01:56 up  7:43,  2 users,  load average: 0.16, 0.21, 0.18
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
Cpu(s):  4.0%us,  0.2%sy,  0.0%ni, 95.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1017324k total,   339492k used,   677832k free,    15880k buffers
Swap:        0k total,        0k used,        0k free,   252196k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 4801 ec2-user  20   0  126m 3564 3248 R 99.9  0.4   0:11.04 cpuload.pl
```
①スクリプト起動後、②"①"の60秒後、③"②"の直後　の計3回topコマンドを実行している。
ヘッダおよびスクリプトのCPU使用率を見てみると、
① ヘッダ：Cpu(s):  4.0%us,  0.2%sy,  0.0%ni, 95.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
　スクリプト：0.0%
② ヘッダ：Cpu(s): 17.6%us,  0.0%sy,  0.0%ni, 82.4%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
　スクリプト：17.5%
③ ヘッダ：Cpu(s):  4.0%us,  0.2%sy,  0.0%ni, 95.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
　スクリプト：99.9%
となっている。

②でTIME+が10秒超であることから、本来はとっくにスクリプトのCPU使用率はほぼ100%のはずだが、①の時点からのCPU時間占有率なので17.5%と低い数値が出ている(sleepの間はCPUを使用していない)。
また、③はヘッダとスクリプトのCPU使用率が大きく乖離してしまっている。これは③で新しくtopコマンドを実行しており、OS起動時からの平均がヘッダに表示されているためで、①のヘッダとほぼ同じ数値になっている。

# まとめ
仕様を理解して表示に惑わされない。
CPUのパフォーマンスを見たい時はtopコマンドを流しっぱなしにして2回目以降の表示を見る(vmstatも同じ)。

ちなみに上の試してみたでやっているが、topコマンドは"-b"でバッチモード、"-d"で更新間隔(秒)、"-n"で更新回数の指定ができる。バッチモードの何が嬉しいかって、ログにtopコマンドのスクリーン更新ごとの表示がきちんと残ること。例えば「webサーバ#1~#3があるけど#1だけなぜかCPU使用率が高い」なんて時に
`# top -b -d 3 -n 100`
と各サーバで実行して、ログで各プロセスを比較してみるのに役立つ。