iowait 是 CPU 的一种状态,表示此时 CPU 正处于 idle 状态,并且至少有一个进程正在等待 IO。
CPU 一共有四种状态。在任一时刻,CPU 的状态都是四种中的一种。这四种状态是:user, sys, idle iowait. 一般的程序,比如 sar
top
,会用百分比表示 CPU 分别处于这四种状态的时间,这四种状态相加的结果是 100%。
其实准确来说,CPU 只有两种状态:busy 和 idle。Busy 又分成了两种,user 和 system,可以表示 CPU 目前正在执行用户空间的代码,还是正在执行 kernel 空间的代码,方便开发者定位问题。Idle 又分成了两种:idle 和 iowait。笼统来说,idle 就是目前系统中没有 Runnable 的进程了(参考之前的博文:Linux 进程的生命周期),iowait 就是目前系统中没有 Runnable 进程(所以说 iowait 是 idle 的一种),并且,有进程卡在 IO 上。
(注意,本文说的“进程”是从资源调度的角度讲的,本文的语境中,进程包括线程)
统计的方式
Kernel 会定期更新 counter(AIX,CPU state counter 每个 clock interrrupt 更新,每 10ms 一个 interrupt)。
对于每次更新,检查 CPU 是否是 busy,如果是 busy,检查 CPU 在执行用户态还是内核态的代码,增加相应的计数器。如果不是 busy,那就是 idle,检查此 CPU 之前有没有发出 IO 操作,如果有,那么就增加 iowait,如果没有,那么就增加 idle 的计数器。(所以可以认为这个数值是抽样统计的方法?)
像 sar,top 这种展示工具,就去读 counter,计算时间段内的比例,展示结果。
举例说明含义
综上,假设 CPU state 出现了比较高的 iowait,那么就意味着:这个 CPU (在大部分时间)找不到可以执行的进程了,至少有一个进程在等待 IO。
iowait 只包括文件系统的 IO,不包括:sockets, pipes, ttys, select(), poll(), sleep(), pause()。
举例1: 一个机器有 4 个 CPU,1个CPU iowait 比较高,3 个 CPU user+sys 很高,iowait 很低。
意思是当前有 3 个 Runnable 的进程,有至少1个进程阻塞在 IO,其他的进程要么阻塞在 IO,要么阻塞在其他状态,但是不是 Runnable 状态,Runnable 状态的进程有且只有 3 个。因为如果再多来一个 Runnable,那么它就会被 iowait 高的那个 CPU 去执行,此 CPU 的 iowait 也不会很高了,user+sys 会变高。
举例2: 这个例子是参考资料 What exactly is “iowait”? 中的,非常典型。
假设有 6 个 CPU,而且只有 6 个进程:
- 2个进程不涉及磁盘 IO 操作,只有 CPU 计算;
- 4个进程要花 70% 的时间做 IO 操作,30% 的时间在 CPU 上计算,这 30% 中,5% 是在 kernel mode,25% 是在 user mode。
那么 CPU 利用率将会如下,最后一行是综合所有的 CPU 的数据:
1 2 3 4 5 6 7 8 |
cpu %usr %sys %wio %idle 0 25 5 70 0 1 25 5 70 0 2 25 5 70 0 3 25 5 70 0 4 100 0 0 0 5 100 0 0 0 - 50 3 47 0 |
现在,还是6个进程完全不变,但是 CPU 从6个减少到了4个,数据将会是如下:
1 2 3 4 5 6 |
cpu %usr %sys %wio %idle 0 50 10 40 0 1 50 10 40 0 2 100 0 0 0 3 100 0 0 0 - 75 5 20 0 |
可以看到,2个 100% 利用率的 CPU 保持不变,但是总的 CPU 的利用率是 80% 了。解释如下。
4个进程,每一个进程只要花 30% 的时间来计算,其他的时间是 iowait,iowait 是 idle 中的一种,iowait 的时候,如果能有别的事情可以做,CPU 就会去做别的事情。所以 2 个 CPU 每一个会花 60% 的时间做计算工作(一个进程是 25% + 5%,做完之后做下一个进程的 25% + 5%)。做完 60% 就无事可做了,剩下 40% 的 iowait(就是 idle)。
总结
iowait 是一种 idle,如果比例过高,它可以告诉我们几件事情:
- 系统正在做的工作,大部分时间都是在等待 io 了,io 系统的性能不够高(也有可能是硬盘坏了);
- CPU 没有更多的工作可以做了,我们可以给系统分配更多的计算工作;
- 它不是 CPU 的一种“阻塞”状态,它不能说明:CPU 现在在等待 IO,无法运行其他进程。而是:没有可以运行的进程能给 CPU 做;
iowiat 是 CPU 角度的一个状态,它不是进程角度的状态。iowait 很低,不能代表进程没有卡在 IO 上。假设有一个进程需要花 70% 的时间做 io操作,把它放到一个空闲的,单 CPU 的系统中,显示的 iowait 是 70%,但是我在这个系统中增加一个不依赖 io 的计算任务,iowait 就变成 0 了。但是我们之前的那个进程,依然需要花 70% 的时间等待 io。所以,它不代表进程的状态。
参考内容: