top,vmstat,iostatとか見てもよくわからない人向けのまとめ



# 背景
負荷試験実施にあたって、
いくつか不足している知識があったため、改めて周辺の知識を整理することで
負荷試験の結果を正確に捉えられるようにしようと思います。


# パフォーマンスでよく確認する項目
- ロードアベレージ
- CPU使用率
- スループット
- メモリ負荷
- I/O負荷

などなど。
パフォーマンスを見る際にどのコマンドのどこにどういう情報が記載してあるか
という観点でまとめていきます。

なお、確認などでいくつかのソースを記載しているが、
実行場所はvagrant環境で構築したCentOS7.6の情報です。

```shell
[vagrant@console ~]$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
```

# 前提知識
まず、確認方法の前に確認項目がどういった概念であるのかを整理。

## プロセス・スレッド・CPU
### プロセスとスレッド
プロセスとは処理の実行単位のこと。
ただ、プロセス内にはスレッドというものが1個以上含まれており、
このスレッドがCPUに対して命令を与える。
プロセス、スレッドともに処理の実行単位であるがスレッドのほうがより粒度が細かい単位である。


### CPU
CPUはコンピュータにおける5台装置のうち、制御装置と演算装置を担う。
OSから割り振られたプロセスをメモリから読み出し処理する役割があるが、
実際に命令を実行するのはCPU内のコアである。


マルチコアなどの名称は1CPU内に複数のコアが付いており、
1つのコアを複数スレッドとOSに認識させる（マルチスレッディング）ことも可能なため、
1CPU内で複数のスレッドを実行することができる。
マルチスレッディングに対応しているCPUであれば、同時に捌けるスレッド数はコア数の2倍である。

なお、コア数っていくつなんだっけは以下で確認が可能。
各プロセッサー（CPU)ごとに情報が記載されている。
そのうち、cpu cores という項目がCORE数であり、
またこれは1プロセッサーごとではなくプロセッサー全体のCORE数となる。

 [Linux上で認識されるCPU(物理CPU/物理コア/論理CPU)の数の確認について](https://kakurasan.hatenadiary.jp/entry/20110117/p1#h-20110117p1-2)
も参考にすると、
コア数が4であることがわかる。


```shell
[vagrant@console ~]$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 158
model name      : Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
stepping        : 9
cpu MHz         : 3600.000
cache size      : 8192 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 4
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch avx2 rdseed clflushopt
bugs            :
bogomips        : 7200.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 158
model name      : Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
stepping        : 9
cpu MHz         : 3600.000
cache size      : 8192 KB
physical id     : 0
siblings        : 4
core id         : 1
cpu cores       : 4
apicid          : 1
initial apicid  : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch avx2 rdseed clflushopt
bugs            :
bogomips        : 7200.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

processor       : 2
vendor_id       : GenuineIntel
cpu family      : 6
model           : 158
model name      : Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
stepping        : 9
cpu MHz         : 3600.000
cache size      : 8192 KB
physical id     : 0
siblings        : 4
core id         : 2
cpu cores       : 4
apicid          : 2
initial apicid  : 2
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch avx2 rdseed clflushopt
bugs            :
bogomips        : 7200.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:

processor       : 3
vendor_id       : GenuineIntel
cpu family      : 6
model           : 158
model name      : Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
stepping        : 9
cpu MHz         : 3600.000
cache size      : 8192 KB
physical id     : 0
siblings        : 4
core id         : 3
cpu cores       : 4
apicid          : 3
initial apicid  : 3
fpu             : yes
fpu_exception   : yes
cpuid level     : 22
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch avx2 rdseed clflushopt
bugs            :
bogomips        : 7200.00
clflush size    : 64
cache_alignment : 64
address sizes   : 39 bits physical, 48 bits virtual
power management:
```


### ロードアベレージ
ロードアベレージは実行中もしくは実行待ちのプロセスの数を
時間毎に平均化した値である。
そのため、実行しているハードウェアのコア数によって、
ロードアベレージの値の捉え方も変わってくる。
具体的には　ロードアベレージ　＞　コア数　となっている場合は処理を捌ききれていないことになるので、
負荷が高い状態（レスポンスが遅い状態）であるといえる。


## メモリ
通常プログラムはストレージ（補助記憶装置/ディスク）に記録されてる。
CPUはプログラム実行時に、
プログラムの命令を主記憶装置（メモリ）にロードし実行する。
実行が終わると主記憶装置から削除（解放）される。

なお、CPU > メモリ > ストレージといった順で処理速度が早くなるため、
各装置間にはキャッシュが置かれている。
それがメモリキャッシュやディスクキャッシュである。

### バッファキャッシュとページキャッシュ
ディスクキャッシュには「バッファキャッシュ」と「ページキャッシュ」の 2種類がある。
バッファキャッシュは、プロセスがディスク上のデータに アクセスする際、
アクセスすべきデータのブロックを高速に見つけるために 使用されるメモリ。

一方のページキャッシュは、ディスク上のデータをページ単位で一時的に
保存するために使用されるメモリでファイルの読み書きの高速化に 使用される。


### スワップ
メモリ容量をより大きく見せるための技術として仮想記憶管理というものがある。
この場合、メモリとストレージ内の仮想メモリ空間の間で、
ページというプログラムを分割したものの置き換えなどをしながらプログラムを実行していく。
※ページ置き換えアルゴリズムはいくつかあるので気になった方は調べてみてください。
メモリと仮想記憶装置間のやりとりは遅いので、
スワップが多くなると処理速度が低下していく。


スワップとはストレージ上に確保された仮想メモリ容量のことをいう。
つまり、メモリの総容量は実質的には
使用中メモリ + メモリキャッシュ　+ 空きメモリ + スワップ
ということになる。


### メモリリーク
アプリケーションやOSなどのバグでメモリの解放ができず、
使用できるメモリ容量が減少していきます。
これがメモリリークです。
解消するにはガベージコレクションもしくは、再起動が必要になります。




#パフォーマンス確認のための各コマンドの見方

## 全体概要の確認　～TOP～
CPU使用率などはCloudWatchのメトリクスなどでも確認できるが、
より細かい時間単位で確認する場合はTopコマンドを使用する。
TOPコマンドはCPU使用率やLoadAverage、Memory情報などが一覧で表示されるため、
全体概要を把握するにの使用されることが多い。
また、単体プロセスの問題であればTopから推測可能である。

```bash

$top
top - 10:49:39 up 26 days, 21:09,  1 user,  load average: 0.03, 0.20, 0.25
Tasks: 151 total,   2 running, 149 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 :  4045736 total,  1219964 free,   824516 used,  2001256 buff/cache
KiB Swap:  2097148 total,  2090612 free,     6536 used.  2541516 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    1 root      20   0  193912   8336   5440 S   0.0  0.2  17:02.13 systemd
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.77 kthreadd
    3 root      20   0       0      0      0 S   0.0  0.0   0:39.29 ksoftirqd/0
```

上記のうち1行目のload averageがload average、
3行目の%Cpu(s)がCPU使用率である。
%Cpu(s)の下にあるのが、メモリ使用量とスワップ使用量である。

### load average
左から直近1分, 5分, 15分間のロードアベレージの値である。

### CPU使用率

| カラム名 | 意味 |
|:-----------------:|:------------------:|
| us | ユーザーが起動したプロセスの使用時間 |
| sy | デーモンなどOSの機能を実現するシステムプロセスの使用時間 |
| ni | 実行優先度を変更したユーザープロセスの使用時間 |
| id | アイドル状態の時間 |
| wa | I/O終了待ちの時間 |
| hi | ハードウェア割り込み要求での使用時間 |
| si | ソフトウェア割り込み要求での使用時間 |
| st | ゲストOSが割り当て要求をしたが、割り当ててもらえなかったCPU使用率 |

負荷試験などで大量にリクエストを投げるとusが劇的に上がり、
syが微増、idは0に近づいていく。

これらを踏まえ、負荷を掛ける前に
Topコマンドの結果をファイル出力しておき、
後で集計を行うのが最も効率的なようである。



### メモリ使用量
基本的にLINUXでは使用されているメモリの残りを
キャッシュなどに使用し、ディスク入出力の負荷を減らしている。
そのため、一見freeがほとんどないこともあるが、
buff/cacheに割り振られていることが多いので落ち着いて確認する必要がある。

また、これを考慮すると、
free + buff/cacheがメモリ残となる。
先程のTop出力結果をみると３G程度は余裕があることがわかる。


なお、ライブラリなどであまり使われていないものに関しては、
スワップ領域へ退避させキャッシュなどにメモリをあてるようにするため、
スワップ領域が使用されていること自体には問題はない。



### プロセスのソート
Topではプロセスの実行中に各プロセスをソートすることが可能。
5行目までに記載の値から問題のありそうなものにあたりをつけてそのカラムでソートする。

| コマンド | コマンド内容 |
|:-----------------:|:------------------:|
| <,> | ソート対象のカラムを選択 |
| P | CPUの使用順でソート |
| M | メモリの使用順でソート |
| R | ソートの降順,昇順を変更 |



## 時系列の確認/スワップ/ioの確認 ～vmstat～
topよりもvmstatのほうがswapやi/oを含めた時系列情報を確認するのに向いている。
基本形は以下。

```
vmstat [オプション] [更新の間隔 [回数]]
```
オプションなし、1秒毎に更新（レコード追加）の場合

```

$ 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
 1  0   6536 1222184    168 2001676    0    0     0    13    1    3  6  0 93  0  0
 0  0   6536 1222184    168 2001676    0    0     0     0  127  182  0  0 100  0  0
 0  0   6536 1222184    168 2001676    0    0     0     0  125  184  0  0 100  0  0
 0  0   6536 1222184    168 2001676    0    0     0     0  105  187  0  0 100  0  0
 0  0   6536 1222184    168 2001676    0    0     0     0   94  171  0  0 100  0  0
 0  0   6536 1222184    168 2001676    0    0     0     8  139  188  0  0 100  0  0
 0  0   6536 1222184    168 2001676    0    0     0     0   99  170  0  0 100  0  0
```

vmstatのあとの1は１秒間隔で表示という意味で、
１秒毎にレコードが追加されるようになる。


| カテゴリ | 項目名 | 意味 |
|:-----------------:|:------------------:|:------------------|
| procs | r | ランタイム待ちのプロセス数 |
| procs | b | 割り込み不可能なスリープ中のプロセス数。ディスクのIO待ちなど。 |
| memory | swpd | スワップ領域のメモリ量。 |
| memory  | free | メモリの空き容量 |
| memory  | buff | メモリバッファの量。情報を一時保存するためにメモリ上に確保された領域。Topの際に説明したようにここが肥大化していても、空き容量換算で基本は問題ない。※空き容量はバッファ、キャッシュに割り当てるようになっているため。よってキャッシュも同様 |
| memory  | cashe | ディスクキャッシュの量。 |
| swap | si | スワップインのデータ量。単位はkbらしい。スワップインとはストレージのスワップ領域からメモリ上にロードを行うこと。 |
| swap | so | スワップアウトのデータ量。単位はkbらしい。スワップアウトとはメモリ上からストレージのスワップ領域へ退避させること。 |
| io | bi | ブロックデバイスから受け取ったブロック数。ブロックの単位は```stat -f /tmp``` でわかるらしい。大抵は4096 byte |
| io | bo | ブロックデバイスへ送られたブロック数。ブロックの単位は```stat -f /tmp``` でわかるらしい。大抵は4096 byte |
| system | in | 割り込み処理の回数 |
| system | cs | プログラムの切り替え回数。CPUは並列処理を行っており、プログラムを切り替えながら実行している。 |
| cpu |  | topと同様のため省略 |


スワップが大量に発生している場合は、メモリ増設を検討する必要がありそうです。
また、procs b（IO待ちプロセス）が高い場合はディスクIOがボトルネックの可能性大といった見かたが可能です。

## ioの確認 ～iostat～

iostatはディスクI/Oの使用状況を表示します。
また、同時にCPU使用率も表示されます。（-d）で省略可能。
コマンドの書式はvmstatと同様。
-xは詳細表示のオプションです。

```bash

$ iostat -x 5
Linux 4.9.20 (console)  01/28/2020      _x86_64_        (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           6.32    0.00    0.25    0.06    0.00   93.37

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.37    0.02    7.30     0.53    51.54    14.22     0.03    4.34   17.29    4.31   1.45   1.06
dm-0              0.00     0.00    0.02    5.74     0.53    51.53    18.07     0.04    6.46   18.25    6.42   1.84   1.06
dm-1              0.00     0.00    0.00    0.00     0.00     0.01     8.28     0.00   26.24   14.82   26.55   0.41   0.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.00    0.00    0.00    0.00    0.00  100.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00    0.40     0.00     1.59     8.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-0              0.00     0.00    0.00    0.40     0.00     1.59     8.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
```

|  |  |
|:-----------------:|:------------------|
| r/s | 秒間の読み込み回数 |
| w/s | 秒間の書き込み回数 |
| avgrq-sz | 平均 I/O サイズ |
| avgqu-sz | 平均待ち行列長 |
| await | レスポンスタイム。I/O を実施していない待ち時間を含む。 |
| svctm | サービスタイム。1回のI/Oに要する時間 (ミリ秒)。 |
| %util| 使用率（ビジー率） |

IOPS(r/s + w/s)が増えて、平均待ち行列長(avgqu-sz)とレスポンスタイム(await)が大きくなっている場合、I/O 回数が増えて待ちが発生していると考えられる。
平均 I/O サイズ(avgrq-sz)が変わらないのにサービスタイム(svctm)が大きくなった場合、I/O性能が劣化しており、ストレージに問題があると考えられる。

## ネットワークの確認 ～netstat～
netstatでネットワーク接続状態や、統計情報を確認することができます。
```netstat -n```で現在TCPコネクションが張られているものの、
ホストアドレス:ポートと接続先アドレス：ポートが表示される。
なお、-nを入れない場合は名前解決前の文字列が表示されます。
また、-aですべての接続とリッスンポートを表示することが可能です。

```bash

$netstat -n
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 255.0.0.0:55920         255.0.0.0:443           ESTABLISHED
tcp        1      0 127.0.0.1:53420         127.0.0.1:8080          CLOSE_WAIT
tcp        0      0 255.0.0.0:32904         255.0.0.0:80            TIME_WAIT
・
・
・
```

ステータスに関しては以下となる。
なお、接続終了の画像は以下から引用している。
 [SECURITY ASSESSMENT OF THE TRANSMISSION CONTROL PROTOCOL (TCP) ](https://web.archive.org/web/20090306052826/http://www.cpni.gov.uk/Docs/tn-03-09-security-assessment-TCP.pdf)

接続確立時
![2020-03-12_104548.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474743/8342a187-af3d-569a-c847-f9b9ebc4a6af.png)



接続終了時

>
![2020-03-12_104538.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474743/aa2471e0-8e9c-b19e-8c41-643c57afe169.png)





接続エラー発生時にどのフェーズが問題になっているかの切り分けなどに使えそうです。

# 終わり
どのコマンドで何が見られるのかまでは整理できたが、
使い分けや見方はもっと洗練できそうです。

# 参考
 [topコマンドの使い方](https://qiita.com/k0kubun/items/7368c323d90f24a00c2f)
 [topコマンドの使い方・見方](https://linuxserver.jp/linux/top%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89/)
 [linuxにおけるメモリと関連コマンド（free, vmstat, top, sar）](https://sisidovski.hatenablog.com/entry/2015/07/07/072150)
 [vmstatコマンドについて調べてみた](https://www.denet.ad.jp/technology/2017/10/vmstat.html)
 [【 iostat 】コマンド――I/Oデバイスの使用状況を表示する](https://www.atmarkit.co.jp/ait/articles/1707/20/news021.html)
 [iostatコマンドの基本的な使い方](https://qiita.com/pyon_kiti_jp/items/a44ac6e9229ba7b90c6b)
 [TCP/IP通信の状態を調べる「netstat」コマンドを使いこなす](https://www.atmarkit.co.jp/ait/articles/0207/20/news003.html)
 [netstat～ホストのネットワーク統計や状態を確認する](https://www.atmarkit.co.jp/fnetwork/netcom/netstat/netstat.html)
 [プログラマーが「ネットワーク怪しくない？」と思った時に覚えておくと便利なことまとめ](https://made.livesense.co.jp/entry/2016/05/10/083000)