iostat Report Central Processing Unit (CPU) statistics and input/output statistics for devices and partitions.
Help
# iostat --help
Usage: iostat [ options ] [ <interval> [ <count> ] ]
Options are:
[ -c ] [ -d ] [ -h ] [ -k | -m ] [ -N ] [ -t ] [ -V ] [ -x ] [ -y ] [ -z ]
[ -j { ID | LABEL | PATH | UUID | ... } ]
[ [ -T ] -g <group_name> ] [ -p [ <device> [,...] | ALL ] ]
[ <device> [...] | ALL ]
参数
- -c 显示 CPU 使用情况
- -d 显示磁盘使用情况
- -k 以 KB 为单位显示
- -m 以 M 为单位显示
- -N 显示磁盘阵列(LVM) 信息
- -n 显示 NFS 使用情况
- -p [磁盘] 显示磁盘和分区的情况
- -t 显示终端和 CPU 的信息
- -x 显示详细信息
- -V 显示版本信息
属性说明
- %user:CPU 处在用户模式下的时间百分比
- %nice:CPU 处在带 NICE 值的用户模式下的时间百分比
- %system:CPU 处在系统模式下的时间百分比
- %iowait:CPU 等待输入输出完成时间的百分比
- %steal:管理程序维护另一个虚拟处理器时,虚拟 CPU 的无意识等待时间百分比
- %idle:CPU 空闲时间百分比
经验说明:
%iowait值过高,表示硬盘存在 I/O 瓶颈
%idle值过高,表示 CPU 较空闲,如果%idle值高但系统响应慢时,有可能是CPU等待分配内存,此时应加大内存容量
- rrqm/s: 每秒进行 merge 的读操作数目。即 rmerge/s
- wrqm/s: 每秒进行 merge 的写操作数目。即 wmerge/s
- r/s: 每秒完成的读 I/O 设备次数。即 rio/s
- w/s: 每秒完成的写 I/O 设备次数。即 wio/s
- rsec/s: 每秒读扇区数。即 rsect/s
- wsec/s: 每秒写扇区数。即 wsect/s
- rkB/s: 每秒读 K 字节数。是 rsect/s 的一半,因为每扇区大小为 512 字节
- wkB/s: 每秒写 K 字节数。是 wsect/s 的一半
- avgrq-sz: 平均每次设备 I/O 操作的数据大小 (扇区)
- avgqu-sz: 平均 I/O 队列长度
- await: 平均每次设备 I/O 操作的等待时间 (毫秒)
- svctm: 平均每次设备 I/O 操作的服务时间 (毫秒)
- %util: 向设备发出 I/O 请求所占用时间的百分比(设备的带宽利用率)
经验说明:
%util 接近 100%,说明产生的 I/O 请求太多,I/O 系统已经满负荷,该磁盘可能存在瓶颈
svctm 比较接近 await,说明 I/O 几乎没有等待时间
await 远大于 svctm,说明 I/O 队列太长,io 响应太慢,则需要进行必要优化
avgqu-sz 比较大,也表示有当量 io 在等待
使用
# iostat -c
Linux 3.10.0-693.el7.x86_64 (node1) 08/19/2020 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.44 0.00 1.74 0.12 0.02 92.68
# iostat -d
Linux 3.10.0-693.el7.x86_64 (node1) 08/19/2020 _x86_64_ (8 CPU)
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sdc 0.00 0.00 0.00 5888 0
sdb 0.00 0.00 0.00 5888 0
scd0 0.00 0.00 0.00 144 0
sda 9.16 13.63 353.34 310574466 8050084426
dm-0 0.00 0.00 0.00 5364 4
# iostat -k
Linux 3.10.0-693.el7.x86_64 (node1) 08/19/2020 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.44 0.00 1.74 0.12 0.02 92.68
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sdc 0.00 0.00 0.00 5888 0
sdb 0.00 0.00 0.00 5888 0
scd0 0.00 0.00 0.00 144 0
sda 9.16 13.63 353.34 310580506 8050100296
dm-0 0.00 0.00 0.00 5364 4
# iostat -m
Linux 3.10.0-693.el7.x86_64 (node1) 08/19/2020 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.44 0.00 1.74 0.12 0.02 92.68
Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn
sdc 0.00 0.00 0.00 5 0
sdb 0.00 0.00 0.00 5 0
scd0 0.00 0.00 0.00 0 0
sda 9.16 0.01 0.35 303301 7861442
dm-0 0.00 0.00 0.00 5 0
# iostat -t
Linux 3.10.0-693.el7.x86_64 (node1) 08/19/2020 _x86_64_ (8 CPU)
08/19/2020 11:08:00 AM
avg-cpu: %user %nice %system %iowait %steal %idle
5.44 0.00 1.74 0.12 0.02 92.68
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sdc 0.00 0.00 0.00 5888 0
sdb 0.00 0.00 0.00 5888 0
scd0 0.00 0.00 0.00 144 0
sda 9.16 13.63 353.34 310580506 8050140517
dm-0 0.00 0.00 0.00 5364 4
# iostat -p sdb -x 1
Linux 3.10.0-693.el7.x86_64 (node1) 10/23/2020 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
5.83 0.00 1.80 0.12 0.02 92.23
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sdb 0.00 0.00 0.00 0.00 0.00 0.00 51.42 0.00 1.76 1.77 0.00 1.42 0.00
iostat -x 3
iostat -xm 1
NVMe SSD 场景下 %util 的局限性
在 NVMe SSD 场景下,传统的 I/O Utilization(利用率,通常指 iostat 中的 %util)确实非常不准,甚至具有误导性。
核心原因在于: 该指标是基于时间计算的,而不是基于性能容量计算的。它是为单队列的机械硬盘(HDD)设计的,无法反映 NVMe 这种多队列、高并发设备的真实负载。
- HDD 时代的 %util:像单窗口的售票处。窗口前只要有人就是 100% 忙,后面的人就得等。
- NVMe 时代的 %util:像拥有 1000 个窗口的超级售票大厅。只要有一个窗口有人在办事,监控系统就报警说
大厅 100% 被占用了(时间维度)。这显然是荒谬的,因为还有 999 个窗口是空的。
%util 的计算公式本身过时了
在 Linux 的 iostat 等工具中,%util 的定义是:在采样周期内,设备有至少一个 I/O 请求在处理(In-flight)的时间比例。
- 公式:
(IO_busy_time / Sampling_interval) * 100%
- 对于 HDD/SATA SSD: 以前的硬盘是串行处理或队列深度很浅(AHCI 通常只有 32)。如果磁盘一直有 I/O 在排队,说明磁盘确实忙不过来了,100% util 基本等于磁盘饱和。
- 对于 NVMe SSD: NVMe 协议支持高达 64K 个队列(Queues),每个队列深度可达 64K。
- 现象: 假设你每秒钟只发几个小的 I/O 请求,只要这些请求在时间轴上连接得很紧密(一个接一个,中间没空闲),
%util 就会显示 100%。
- 真相: 此时 NVMe 可能只发挥了其并发能力的 0.1%,它就像一个拥有 64000 个车道的高速公路,虽然一直有一辆车在跑(时间上由占用),但剩下的 63999 个车道都是空的。
并发能力(Parallelism)被忽略
NVMe 的核心优势是并发。
- 传统指标视角的饱和: 只要有工人在干活,就叫
忙(Util 100%)。
- NVMe 的真实饱和: 必须所有工人都满负荷干活,才叫
忙。
如果你的 NVMe SSD %util 是 100%,但平均队列深度(avgqu-sz)只有 1 或者 2,说明硬盘根本没有压力。只有当队列深度达到几百甚至上千(取决于具体 SSD 的性能),才真正接近物理瓶颈。
什么是正确的分析姿势?
既然 %util 不准,分析 NVMe 性能瓶颈应该看什么?请关注以下三个核心指标:
- 响应时间/延迟 (Latency) —— 这是金标准
- 指标:
await (总等待时间), r_await (读延迟), w_await (写延迟)。
- 分析方法:
- 如果不看
%util,只看 await。
- 正常的企业级 NVMe SSD,在低负载下延迟通常在 50μs - 200μs (0.05ms - 0.2ms) 之间。
- 如果
%util 飙升到 100%,但 await 依然保持在 0.1ms - 0.5ms 级别,说明没有瓶颈,忽略 %util 即可。
- 只有当
await 显著上升(例如超过 5ms 或 10ms),才说明 I/O 真的拥堵了。
- 队列深度 (Queue Depth)
- 指标:
aqu-sz 或 avgqu-sz。
- 分析方法:
- 观察当前的排队数量。
- 对于 NVMe,如果
avgqu-sz 长期远小于该设备的标称最大并发数(通常 NVMe 支持极高并发),则说明未饱和。
- 吞吐量与 IOPS (Throughput / IOPS)
- 指标:
r/s, w/s (IOPS) 和 rkB/s, wkB/s (带宽)。
- 分析方法:
- 直接对比厂商提供的 Spec(规格书)。
- 例如:Spec 说支持 3GB/s 写入,现在只有 500MB/s,但
%util 100%。此时结合延迟看,如果延迟很低,说明是应用发得不够快,而不是盘不行;如果延迟很高,可能是盘的垃圾回收(GC)在作怪或寿命将尽。
建议使用的命令与关注点:
# 使用 iostat 扩展模式
iostat -x -d 1
# 重点看这几列:
# r_await / w_await : 只要这两个低(<1ms),盘就是健康的。
# aqu-sz : 真正堆积的任务数量。
# %util : 直接忽略。
如果需要更深度的分析(例如分析是内核层拥堵还是设备层拥堵),建议使用 eBPF 工具(如 bcc-tools 中的 biolatency 或 biosnoop),它们能生成延迟的直方图,比平均值更准确。
查看 NVMe SSD 的队列深度
使用 nvme-cli 工具,查看 NVMe 设备的队列数量(Number of Queues)和队列深度(Queue Depth):
先安装 nvme-cli (apt install nvme-cli 或 yum install nvme-cli)
查看队列数量
使用 get-feature 命令读取 Feature ID 0x07 (Number of Queues)。
# 语法:nvme get-feature <设备路径> -f 7
sudo nvme get-feature /dev/nvme0 -f 7
- 输出示例:
get-feature:0x7 (Number of Queues), Current value:0x3f003f
- 解读: 结果是十六进制的。
- 低 16 位 (
003f -> 63) 是 Submission Queues (SQ) 的数量。
- 高 16 位 (
003f -> 63) 是 Completion Queues (CQ) 的数量。
- 注:这里显示的通常是 I/O 队列的数量,不包含 Admin 队列。
查看队列深度(Queue Depth)
通常没有直接的命令查硬件最大深度,但可以通过 id-ctrl 查看控制器支持的能力。
sudo nvme id-ctrl /dev/nvme0 -H | grep "mqes"
- mqes (Maximum Queue Entries Supported): 硬件支持的最大队列深度(例如 65535)。
要查看当前操作系统层生效的队列深度(软件限制):
cat /sys/block/nvme0n1/queue/nr_requests