Linux iowait
本文主要参考 The precise meaning of I/O wait time in Linux
Linux 中 CPU 的使用统计被拆分成多个组成部分,
最常见的如 sys 表示 CPU 在内核态的使用情况,usr CPU 在用户态的使用情况。
iowait 也是其中一种,它表示 CPU 等待 io 操作的时间。
和其他项相比 iowait 有一个非常特殊的地方:
- iowait 高的时候,CPU 的使用率也会变高,但此时 CPU 本身并不繁忙
- iowait 高的时候表示系统存在 io 瓶颈,但 iowait 低的时候并不代表系统 io 空闲
第一点其实很好理解,iowait 高,表示 CPU 在等待 io 操作,CPU 自己其实正处于休眠状态,
这个时候高 CPU 并不代表 CPU 使用率真的很高。
既然 iowait 高的时候 CPU 本质上是处于休眠状态,此时如果有一个计算密集型的进程需要 CPU 资源,
Linux 就可以把进程调度到休眠中的 CPU 上执行,
这会到时该 CPU 的 usr/sys 变高,相应的它的 iowait 值就会降下来了,
所以,当我们看到 iowait 低的时候,并不能得出系统 io 不繁忙的结论。
我们可以通过一些简单的测试来验证以上的观点:
我们通过dd
指令来模拟 io 繁忙的情况,并且利用taskset
把它调度到 CPU 4 上这执行:
taskset 0x04 dd if=/dev/sdc of=/dev/null bs=4M
通过mpstat
观察各个 CPU 的使用情况:
$ mpstat -P ALL 2
...
22时54分34秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22时54分36秒 all 9.63 0.00 5.32 8.11 0.00 0.19 0.00 0.00 0.00 76.76
22时54分36秒 0 10.45 0.00 4.98 1.00 0.00 0.50 0.00 0.00 0.00 83.08
22时54分36秒 1 11.94 0.00 6.47 0.00 0.00 0.50 0.00 0.00 0.00 81.09
22时54分36秒 2 6.67 0.00 8.21 64.10 0.00 0.51 0.00 0.00 0.00 20.51
22时54分36秒 3 10.20 0.00 2.55 0.00 0.00 0.00 0.00 0.00 0.00 87.24
22时54分36秒 4 8.72 0.00 5.13 0.00 0.00 0.00 0.00 0.00 0.00 86.15
22时54分36秒 5 8.12 0.00 9.14 0.00 0.00 0.00 0.00 0.00 0.00 82.74
22时54分36秒 6 10.71 0.00 3.06 0.00 0.00 0.00 0.00 0.00 0.00 86.22
22时54分36秒 7 10.15 0.00 2.54 0.51 0.00 0.00 0.00 0.00 0.00 86.80
22时54分36秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22时54分38秒 all 11.12 0.00 5.56 7.39 0.00 0.32 0.00 0.00 0.00 75.62
22时54分38秒 0 12.56 0.00 6.03 0.00 0.00 0.50 0.00 0.00 0.00 80.90
22时54分38秒 1 10.10 0.00 10.61 0.00 0.00 0.51 0.00 0.00 0.00 78.79
22时54分38秒 2 9.18 0.00 10.71 59.18 0.00 0.00 0.00 0.00 0.00 20.92
22时54分38秒 3 13.57 0.00 3.02 0.00 0.00 0.50 0.00 0.00 0.00 82.91
22时54分38秒 4 11.22 0.00 3.06 0.00 0.00 0.51 0.00 0.00 0.00 85.20
22时54分38秒 5 11.00 0.00 4.00 0.00 0.00 0.50 0.00 0.00 0.00 84.50
22时54分38秒 6 10.71 0.00 3.06 0.00 0.00 0.00 0.00 0.00 0.00 86.22
22时54分38秒 7 10.61 0.00 4.04 0.00 0.00 0.00 0.00 0.00 0.00 85.35
...
可以看到 CPU 4 的 iowait 一直上升到 60% 左右。
再来把一个计算密集型的进程调度到 CPU 4 上执行,然后观察 CPU 4 的使用情况:
taskset 0x04 sh -c "while true; do true; done"
...
22时57分42秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22时57分44秒 all 11.03 0.00 5.36 6.55 0.00 0.25 0.00 0.00 0.00 76.81
22时57分44秒 0 9.50 0.00 5.00 0.00 0.00 0.50 0.00 0.00 0.00 85.00
22时57分44秒 1 10.34 0.00 10.34 0.00 0.00 0.49 0.00 0.00 0.00 78.82
22时57分44秒 2 27.45 0.00 10.78 50.00 0.00 0.49 0.00 0.00 0.00 11.27
22时57分44秒 3 6.06 0.00 5.05 0.00 0.00 0.51 0.00 0.00 0.00 88.38
22时57分44秒 4 6.22 0.00 2.07 0.00 0.00 0.52 0.00 0.00 0.00 91.19
22时57分44秒 5 6.70 0.00 2.58 0.52 0.00 0.00 0.00 0.00 0.00 90.21
22时57分44秒 6 12.00 0.00 2.00 0.50 0.00 0.00 0.00 0.00 0.00 85.50
22时57分44秒 7 9.09 0.00 4.55 0.51 0.00 0.00 0.00 0.00 0.00 85.86
22时57分44秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22时57分46秒 all 18.50 0.00 4.08 0.13 0.00 0.44 0.00 0.00 0.00 76.87
22时57分46秒 0 8.42 0.00 7.43 0.50 0.00 0.50 0.00 0.00 0.00 83.17
22时57分46秒 1 7.96 0.00 1.99 0.50 0.00 1.00 0.00 0.00 0.00 88.56
22时57分46秒 2 95.98 0.00 4.02 0.00 0.00 0.00 0.00 0.00 0.00 0.00
22时57分46秒 3 7.58 0.00 4.04 0.00 0.00 0.00 0.00 0.00 0.00 88.38
22时57分46秒 4 5.15 0.00 5.67 0.00 0.00 1.03 0.00 0.00 0.00 88.14
22时57分46秒 5 7.46 0.00 2.99 0.00 0.00 0.00 0.00 0.00 0.00 89.55
22时57分46秒 6 7.61 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 91.37
22时57分46秒 7 7.54 0.00 5.03 0.00 0.00 0.00 0.00 0.00 0.00 87.44
22时57分46秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22时57分48秒 all 17.58 0.00 3.57 0.44 0.00 0.81 0.00 0.00 0.00 77.60
22时57分48秒 0 6.86 0.00 7.84 0.49 0.00 0.98 0.00 0.00 0.00 83.82
22时57分48秒 1 10.05 0.00 2.87 0.48 0.00 1.44 0.00 0.00 0.00 85.17
22时57分48秒 2 93.00 0.00 3.00 0.00 0.00 4.00 0.00 0.00 0.00 0.00
22时57分48秒 3 6.12 0.00 3.57 1.53 0.00 0.00 0.00 0.00 0.00 88.78
22时57分48秒 4 7.46 0.00 3.48 1.00 0.00 0.00 0.00 0.00 0.00 88.06
22时57分48秒 5 4.12 0.00 1.55 0.00 0.00 0.00 0.00 0.00 0.00 94.33
22时57分48秒 6 7.54 0.00 2.51 0.50 0.00 0.00 0.00 0.00 0.00 89.45
22时57分48秒 7 5.61 0.00 3.57 0.00 0.00 0.00 0.00 0.00 0.00 90.82
可以看到 iowait 里面降下来了,而 usr 飙到将近 100。所以单纯的观察 iowait 无法对系统的 io 使用情况下结论。
那如何确定系统的 io 使用情况呢?我们可以结合 iostat 来观察:
$ iostat -d 2
...
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
loop0 0.00 0.00 0.00 8 0
sda 1.52 136.33 0.02 13560549 2312
sdb 5.29 42.84 48.49 4261263 4822780
sdc 1.21 553.01 0.00 55006268 0
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
loop0 0.00 0.00 0.00 0 0
sda 0.00 0.00 0.00 0 0
sdb 17.50 72.00 0.00 144 0
sdc 106.50 72704.00 0.00 145408 0
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
loop0 0.00 0.00 0.00 0 0
sda 0.00 0.00 0.00 0 0
sdb 51.50 888.00 30.00 1776 60
sdc 108.50 74240.00 0.00 148480 0
可以很明显的看到 sdc 设备上有大量的读操作。