ロードアベレージについて確認した時のメモ

ロードアレベージについて以下を実施しながら、確認した時のメモ。
（下記の内容を自分でも実際に手を動かしながら試しただけなので元の記事の方が詳しくより丁寧です...）

+ [LinuxのI/OやCPUの負荷とロードアベレージの関係を詳しく見てみる](https://qiita.com/kunihirotanaka/items/21194f77713aa0663e3b)

# 参考

+ [LinuxのI/OやCPUの負荷とロードアベレージの関係を詳しく見てみる](https://qiita.com/kunihirotanaka/items/21194f77713aa0663e3b)
+ [[24時間365日] サーバ/インフラを支える技術 ‾スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ) (日本語) 単行本（ソフトカバー）](https://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)

検証は EC2 の vCPU 1 の t2.micro で試した。

# まとめ

+ ロードアベレージは CPU 負荷もしくは IO 負荷によって高くなる
+ CPU 負荷が掛かっている場合にユーザー側（プログラムなど）かシステム側（システムコールによるカーネルコードの実行など）のどちらに負荷が掛かっているかは `vmstat` や `top` の `us` もしくは `sy` のどちらの値が高いかが参考になる


# 検証コード

以下に記載して頂いているコードを使って同じような検証する。

[LinuxのI/OやCPUの負荷とロードアベレージの関係を詳しく見てみる](https://qiita.com/kunihirotanaka/items/21194f77713aa0663e3b)

```loadtest.pl
#!/bin/perl
my $nprocs = $ARGV[0] || 1;
for( my $i=0; $i<$nprocs; $i++ ){
        my $pid = fork;
        die $! if( $pid < 0 );
        if( $pid == 0 ){
                while(1){
                        if( $ARGV[1] ){
                                open(IN, ">/dev/null");
                                close(IN);
                        }
                }
        }
}
wait;
```

1つ目の引数の数だけプロセスを生成し、生成された子プロセスは無限ループする

```bash
# 1無限ループ
$./loadtest.pl 1

# 4無限ループ
$./loadtest.pl 4
```

さらに第2引数に1を指定すると open/close システムコールを無限ループで呼ぶようにしてカーネルの負荷を掛けるという仕組み。

と、思っていますが違っていたらすいません...

# 検証

## `vmstat` で見れる情報について確認

`man vmstat` で見てみる。

```
FIELD DESCRIPTION FOR VM MODE
   Procs
       r: The number of runnable processes (running or waiting for run time).
       b: The number of processes in uninterruptible sleep.

   Memory
       swpd: the amount of virtual memory used.
       free: the amount of idle memory.
       buff: the amount of memory used as buffers.
       cache: the amount of memory used as cache.
       inact: the amount of inactive memory.  (-a option)
       active: the amount of active memory.  (-a option)

   Swap
       si: Amount of memory swapped in from disk (/s).
       so: Amount of memory swapped to disk (/s).

   IO
       bi: Blocks received from a block device (blocks/s).
       bo: Blocks sent to a block device (blocks/s).

   System
       in: The number of interrupts per second, including the clock.
       cs: The number of context switches per second.

   CPU
       These are percentages of total CPU time.
       us: Time spent running non-kernel code.  (user time, including nice time)
       sy: Time spent running kernel code.  (system time)
       id: Time spent idle.  Prior to Linux 2.5.41, this includes IO-wait time.
       wa: Time spent waiting for IO.  Prior to Linux 2.5.41, included in idle.
       st: Time stolen from a virtual machine.  Prior to Linux 2.6.11, unknown.
```

こんな感じ。
これを念頭に置いて調べる。

## 無限ループで CPU 負荷を掛ける

まずは1無限ループで試す

```bash
# 1無限ループ
$./loadtest.pl 1
```

別のターミナルでみてみる。

```bash
$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      0 553804   2088 382580    0    0    91   123  119  177 37  0 62  0  1
 1  0      0 553680   2088 382580    0    0     0     0  260   65 100  0  0  0  0
 1  0      0 553680   2088 382580    0    0     0     0  257   85 100  0  0  0  0
 1  0      0 553680   2088 382580    0    0     0     0  255   65 100  0  0  0  0
 1  0      0 553680   2088 382580    0    0     0     0  258   79 100  0  0  0  0
 1  0      0 553680   2088 382580    0    0     0     0  254   63 100  0  0  0  0
 1  0      0 553680   2088 382580    0    0     0     0  257   80 100  0  0  0  0
 1  0      0 553680   2088 382580    0    0     0     0  254   64 100  0  0  0  0
```

`vmstat 1` の結果を見ると `us` 列が高い。

`us` は `Time spent running non-kernel code.  (user time, including nice time)` ということでカーネルじゃない利用した時間。
つまり、今回の場合プログラムで時間がかかっている、という状態(無限ループしているので)

`top` はこんな感じ。

```
top - 07:57:34 up 32 min,  3 users,  load average: 0.88, 1.15, 1.16
Tasks:  91 total,   2 running,  53 sleeping,   0 stopped,   0 zombie
%Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1006944 total,   553432 free,    68844 used,   384668 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   797376 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
 3750 ec2-user  20   0  134580    400      0 R 99.9  0.0   2:02.55 loadtest.pl
```

まず、CPU 負荷が掛かっており、1プロセスが CPU を使っている状態で `load average` が1に近い。
また、`vmstat` と同じように CPU 使用率の `us` 列が高くなかっている。

次に無限ループ4で試す。

```bash
$./loadtest.pl 4
```

```
$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
 4  0      0 552280   2088 382852    0    0    74   101  140  165 47  0 52  0  1
 4  0      0 552280   2088 382852    0    0     0     0  260  281 100  0  0  0  0
 4  0      0 552280   2088 382852    0    0     0     0  256  275 100  0  0  0  0
 4  0      0 552280   2088 382852    0    0     0     0  255  274 100  0  0  0  0
^C
```

こんな感じ。
r が4になった。
`r` は `The number of runnable processes` となっており実行しているプロセス数を示す。
4並行で実行しているので正しい。
また、今度も us は 100 となっている。
コンテキストスイッチを示す `cs` も高めの値になっている。
これは4プロセスが頻繁に切り替わっているからだと思われる。

`top` を見る。

```bash
$top
top - 08:04:00 up 38 min,  3 users,  load average: 3.84, 2.36, 1.61
Tasks:  96 total,   6 running,  54 sleeping,   0 stopped,   0 zombie
%Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1006944 total,   552096 free,    69908 used,   384940 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   796252 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
 3765 ec2-user  20   0  134580    400      0 R 25.7  0.0   0:46.17 /bin/perl .+
 3767 ec2-user  20   0  134580    400      0 R 25.7  0.0   0:46.17 /bin/perl .+
 3764 ec2-user  20   0  134580    400      0 R 22.9  0.0   0:46.16 /bin/perl .+
 3766 ec2-user  20   0  134580    400      0 R 22.9  0.0   0:46.16 /bin/perl .
```

`load average` は4に収束して言っているように見える。
つまり、「平均4プロセスが待ち状態になっている」ことを示す。
4プロセスで同じぐらい CPU を使っているので CPU 使用率は 25 ほどになる。


# カーネル負荷を発生させる

`open/close` システムコールをたくさん呼んで負荷を確認する


```bash
$./loadtest.pl 4 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
 4  0      0 519764   2088 407820    0    0     2   103   15   24  2  0 98  0  0
 4  0      0 519756   2088 407820    0    0     0     0  259 1017 58 42  0  0  0
 4  0      0 519748   2088 407820    0    0     0     3  255 1025 60 40  0  0  0
 4  0      0 519748   2088 407820    0    0     0     0  253 1028 58 42  0  0  0
 4  0      0 519748   2088 407820    0    0     0     0  254 1029 62 38  0  0  0
 4  0      0 519756   2088 407820    0    0     0     0  254 1031 57 43  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  255 1028 57 43  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  254 1030 53 47  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  254 1029 60 40  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  254 1023 53 46  0  0  1
 4  0      0 519632   2088 407820    0    0     0     0  254 1031 62 38  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  255 1032 58 42  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  255 1034 65 35  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  254 1029 62 38  0  0  0
 4  0      0 519624   2088 407820    0    0     0     0  255 1030 64 36  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  254 1030 56 44  0  0  0
 4  0      0 519632   2088 407820    0    0     0     0  254 1030 64 36  0  0  0
^C
```

無限ループのときと比べると `sy` 列と `cs` 列が非常に高い。

`top` でも見てみる。

```bash
top - 08:33:46 up 1 day,  1:08,  3 users,  load average: 4.05, 3.70, 2.22
Tasks:  96 total,   7 running,  55 sleeping,   0 stopped,   0 zombie
%Cpu(s): 59.0 us, 41.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1006944 total,   513032 free,    82792 used,   411120 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   767960 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
 8707 ec2-user  20   0  134580    400      0 R 25.0  0.0   3:00.60 loadtest.pl
 8709 ec2-user  20   0  134580    400      0 R 25.0  0.0   3:00.60 loadtest.pl
 8706 ec2-user  20   0  134580    400      0 R 24.7  0.0   3:00.59 loadtest.pl
 8708 ec2-user  20   0  134580    400      0 R 24.7  0.0   3:00.59 loadtest.pl
```

こちらも同じように `sy` が高い値となっている。
無限ループのときと比較すると差分があるのでこれを理解しておくとどこで負荷が掛かっているのか特定する時に役に立ちそう

# I/O負荷を上昇させてみる

load averageは IO 待ちも含むため、IO の負荷を掛けてみて確認する。
これでもload averageは上がるはず。

```bash
$ dd if=/dev/zero of=test bs=1M count=512 oflag=direct
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 7.39068 s, 72.6 MB/s
```

```
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
 0  1      0 552476   2088 382940    0    0    52   322  163  187 56  0 42  0  1
 0  1      0 552468   2088 382940    0    0     0 62464  537  219  0  1  0 98  1
 0  1      0 552468   2088 382940    0    0     0 62464  521  196  0  1  0 99  0
 0  1      0 552468   2088 382940    0    0     0 62464  528  212  0  1  0 98  1
 0  0      0 553204   2088 382940    0    0     0 60416  521  213  0  1  3 95  1
 ```

まず `vmstat` でみると `io` 列が増えているのが分かる。
次にこのときの top でロードアベレージを見てみる。

と思ったがすぐ終わるので以下にする

```
dd if=/dev/zero of=test bs=1M count=1000000 oflag=direct
```

この場合、`top` では CPU 使用率は増えないがload averageはどんどん上がる状況になった。
これは IO 待ちプロセス数も load average には含まれる為だと思われる