ロードアレベージについて以下を実施しながら、確認した時のメモ。
(下記の内容を自分でも実際に手を動かしながら試しただけなので元の記事の方が詳しくより丁寧です...)
参考
- LinuxのI/OやCPUの負荷とロードアベレージの関係を詳しく見てみる
- [24時間365日] サーバ/インフラを支える技術 ‾スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ) (日本語) 単行本(ソフトカバー)
検証は EC2 の vCPU 1 の t2.micro で試した。
まとめ
- ロードアベレージは CPU 負荷もしくは IO 負荷によって高くなる
- CPU 負荷が掛かっている場合にユーザー側(プログラムなど)かシステム側(システムコールによるカーネルコードの実行など)のどちらに負荷が掛かっているかは
vmstat
やtop
のus
もしくはsy
のどちらの値が高いかが参考になる
検証コード
以下に記載して頂いているコードを使って同じような検証する。
LinuxのI/OやCPUの負荷とロードアベレージの関係を詳しく見てみる
# !/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つ目の引数の数だけプロセスを生成し、生成された子プロセスは無限ループする
# 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無限ループで試す
# 1無限ループ
$./loadtest.pl 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 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で試す。
$./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
を見る。
$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
システムコールをたくさん呼んで負荷を確認する
$./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
でも見てみる。
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は上がるはず。
$ 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 には含まれる為だと思われる