我的基本假设是,当进程的唯一限制因素是磁盘和CPU时,总的系统“ iowait” + CPU使用率应至少等于一个逻辑CPU的100%。(在其他情况下,这将不成立。例如,使用来下载文件时wget,网络通常是限制因素)。
一个简单的测试违反了这一假设。这是预期的吗?如果可以预期,是否有一些条件可以期望我的假设成立?
这里有一些有关“ iowait”的背景:CPU如何知道有IO待处理? 这里的答案引用了违反直觉的想法,即累积的iowait“在某些情况下可能会减少”。我想知道我的简单测试是否会触发这种无证的情况?
更新:请跳到答案。
答案比我最初使用的答案更简单。我保留了下面的原始问题。原始问题可能会显示一些其他详细信息。
原始问题
在简短测试中,我用于dd请求内核生成随机字节,并将其写入文件。我在dd内部运行命令perf stat,只是为了计算内核内部花费的CPU时间。我还在内部运行它perf trace -s,以报告在内部花费的时间write()。同时,我vmstat 5在另一个终端上运行,以查看系统“ iowait”。
- 我希望至少将整个CPU视为“非空闲”状态,即100%的时间它正在运行或已暂停但正在等待IO(“ iowait”状态)。不是。
- (此外,我期望看到“ iowait”时间大致与在write()中花费的时间相匹配。但是似乎没有这样做。)
详细结果和测试环境如下所示。还显示了替代测试,我的假设成立了。注意:有必要在perf stat内部运行perf trace,而不是相反。在此进行详细说明:运行“ perf trace-s”时,“ perf stat”(和“ time”!)显示的结果不正确吗?
关于“ iowait”的背景信息
以下是手册
sar页中的定义:%iowait:
在系统有未完成的磁盘I / O请求的过程中,一个或多个CPU空闲的时间百分比。
因此,%iowait意味着从CPU的角度来看,没有可运行的任务,但是至少有一个I / O正在运行。iowait只是空闲时间的一种形式,无法安排任何时间。该值在指示性能问题上可能有用也可能没有用,但是它确实告诉用户系统处于空闲状态,并且可能需要进行更多工作。
https://support.hpe.com/hpsc/doc/public/display?docId=c02783994
还有更长的文章:了解I / O等待(或为什么可以选择0%Idle)。这说明了如何从内核代码清楚地看到定义。代码有所更改,但思路仍然很明确:
/*
* Account for idle time.
* @cputime: the CPU time spent in idle wait
*/
void account_idle_time(u64 cputime)
{
u64 *cpustat = kcpustat_this_cpu->cpustat;
struct rq *rq = this_rq();
if (atomic_read(&rq->nr_iowait) > 0)
cpustat[CPUTIME_IOWAIT] += cputime;
else
cpustat[CPUTIME_IDLE] += cputime;
}
本文还显示了在单CPU系统上的许多相关实验。有些实验甚至dd与if=/dev/urandom !但是实验不包括我的测试dd if=/dev/urandom of=test.out 。它仅使用dd if=/dev/urandom of=/dev/null 。
现在考虑“ IO等待”要棘手一些,因为我们使用的是多CPU系统,但是我仍然基于引用的代码理解它。
环境
我有四个逻辑CPU。
我使用LVM和ext4文件系统。我没有在磁盘或文件系统上使用任何加密。我根本没有安装任何网络文件系统,因此我没有读写网络文件系统。
以下结果来自内核4.20.15-200.fc29.x86_64,使用noopIO调度程序。该cfqIO调度也给出了类似的结果。
(在基于类似配置的内核构建上,我也看到了类似的结果,但更接近于内核版本5.1,并使用mq-deadline。因此使用的是新blk-mq代码)。
测试与结果
$ sudo perf trace -s \
perf stat \
dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000
3000+0 records in
3000+0 records out
3145728000 bytes (3.1 GB, 2.9 GiB) copied, 31.397 s, 100 MB/s
Performance counter stats for 'dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000':
18,014.26 msec task-clock # 0.574 CPUs utilized
3,199 context-switches # 0.178 K/sec
4 cpu-migrations # 0.000 K/sec
328 page-faults # 0.018 K/sec
45,232,163,658 cycles # 2.511 GHz
74,538,278,379 instructions # 1.65 insn per cycle
4,372,725,344 branches # 242.737 M/sec
4,650,429 branch-misses # 0.11% of all branches
31.398466725 seconds time elapsed
0.006966000 seconds user
17.910332000 seconds sys
Summary of events:
...
dd (4620), 12156 events, 12.0%
syscall calls total min avg max stddev
(msec) (msec) (msec) (msec) (%)
--------------- -------- --------- --------- --------- --------- ------
read 3007 17624.985 0.002 5.861 12.345 0.21%
write 3003 13722.837 0.004 4.570 179.928 2.63%
openat 12 0.371 0.002 0.031 0.267 70.36%
...
我iowait从的wa列中读取了该图vmstat。您可以通过查看io列(bo= 1K块输出)来判断测试何时运行。
$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 5126892 176512 1486060 0 0 1788 4072 321 414 4 4 83 9 0
1 0 0 5126632 176520 1485988 0 0 0 7 212 405 0 1 99 0 0
0 0 0 5126884 176520 1485988 0 0 0 0 130 283 0 0 99 0 0
0 0 0 5126948 176520 1485908 0 0 0 1 157 325 0 0 99 0 0
0 0 0 5126412 176520 1486412 0 0 115 0 141 284 0 0 99 0 0
0 2 0 5115724 176548 1487056 0 0 0 6019 18737 10733 3 6 89 2 0
1 0 0 5115708 176580 1487104 0 0 3 91840 1276 990 0 13 77 9 0
1 0 0 5115204 176600 1487128 0 0 2 91382 1382 1014 0 14 81 4 0
1 0 0 5115268 176636 1487084 0 0 4 88281 1257 901 0 14 83 3 0
0 1 0 5113504 177028 1487764 0 0 77 92596 1374 1111 0 15 83 2 0
1 0 0 5114008 177036 1487768 0 0 0 113282 1460 1060 0 16 81 2 0
1 0 0 5113472 177044 1487792 0 0 0 110821 1489 1118 0 16 74 10 0
0 0 0 5123852 177068 1487896 0 0 0 20537 631 714 1 3 94 2 0
0 0 0 5123852 177076 1487856 0 0 0 10 324 529 2 1 98 0 0
2 0 0 5123852 177084 1487872 0 0 0 70 150 299 0 0 99 0 0
测试结果(虚拟机内部)
我在具有1个CPU的VM内尝试了相同的测试,该VM正在运行内核5.0.9-301.fc30.x86_64并使用mq-deadline(因此使用blk-mq)。在此测试中,它按我预期的那样工作。
$ sudo perf trace -s \
perf stat \
dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000
[sudo] password for alan-sysop:
3000+0 records in
3000+0 records out
3145728000 bytes (3.1 GB, 2.9 GiB) copied, 46.8071 s, 67.2 MB/s
Performance counter stats for 'dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000':
18,734.89 msec task-clock # 0.400 CPUs utilized
16,690 context-switches # 0.891 K/sec
0 cpu-migrations # 0.000 K/sec
328 page-faults # 0.018 K/sec
<not supported> cycles
<not supported> instructions
<not supported> branches
<not supported> branch-misses
46.820355993 seconds time elapsed
0.011840000 seconds user
18.531449000 seconds sys
Summary of events:
...
dd (1492), 12156 events, 38.4%
syscall calls total min avg max stddev
(msec) (msec) (msec) (msec) (%)
--------------- -------- --------- --------- --------- --------- ------
write 3003 28269.070 0.019 9.414 5764.657 22.39%
read 3007 18371.469 0.013 6.110 14.848 0.53%
execve 6 10.399 0.012 1.733 10.328 99.18%
...
输出vmstat 5:
$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 726176 52128 498508 0 0 2040 231 236 731 7 5 77 11 0
0 0 0 726176 52136 498508 0 0 0 10 25 46 0 0 99 1 0
0 0 0 726208 52136 498508 0 0 0 0 29 56 0 0 100 0 0
0 1 0 702280 55944 511780 0 0 2260 13109 4399 9049 3 17 55 25 0
0 1 0 701776 56040 511960 0 0 18 129582 1406 1458 0 73 0 27 0
0 2 0 701524 56156 512168 0 0 22 87060 960 991 0 50 0 50 0
3 1 0 701524 56228 512328 0 0 14 118170 1301 1322 0 68 0 32 0
1 1 0 701272 56260 512392 0 0 6 86426 994 982 0 53 0 46 0
0 2 0 701020 56292 512456 0 0 6 56115 683 660 0 37 0 63 0
3 2 0 700540 56316 512504 0 0 5 33450 446 457 0 26 0 74 0
0 2 0 700860 56332 512536 0 0 3 16998 311 240 0 19 0 81 0
1 2 0 700668 56368 512616 0 0 7 32563 443 428 0 24 0 76 0
1 0 0 700668 56392 512648 0 0 3 20338 245 272 0 12 0 88 0
0 1 0 707096 56408 512920 0 0 54 20913 312 530 0 12 79 8 0
0 0 0 707064 56432 512920 0 0 0 49 39 64 0 0 45 55 0
0 0 0 707064 56432 512920 0 0 0 0 24 46 0 0 100 0 0
0 0 0 707064 56432 512920 0 0 0 80 28 47 0 0 100 0 0
我尝试将CPU热添加到VM并再次进行测试。结果是可变的:有时在空闲列中显示为0%,有时显示约50%空闲(即,两个CPU中的一个)。在“空闲”为0%的情况下,“ iowait”非常高,即一个CPU的价值超过一个。即我的期望点2是不正确的。我可以接受在多CPU系统上这种 “ iowait”的明显限制。(尽管我不太了解它。如果有人想确切地解释它,那将很棒)。但是,无论哪种情况,“空闲”都不会超过50%,因此这些测试仍然与我对“ iowait”的第一个假设相一致。
我尝试关闭VM,并以4个CPU启动它。同样,通常我有75%的空闲时间,有时我只有50%的空闲时间,但是我看不到超过75%的空闲时间(即,四个CPU中有三个以上)。
在具有4个CPU的物理系统上,我仍然可以重现80%以上空闲状态的结果,如上所示。
this_rq()->nr_iowait正在等待使用的任务数。我错了吗?io_schedule()
iowait一般来说,它试图衡量等待I / O所花费的时间。它不是由特定的CPU跟踪的,也不是。” 让我强调一点,我不确定,只是表示惊讶。
atop或atopsar -c 5,则将看到每个CPU的使用情况数字。它们包括iowait,每个CPU的iowait数字可以显示不同的非零值:-)。或者sar -P ALL 1,如果您不使用atop。这是该iowait模型已扩展到多CPU系统的方式...我不清楚的是该模型是否实际可用,还是只有当有一个CPU时,这种方式才能使iowait代码继续工作在线,但否则不值得信赖。