blktrace 需内核支持(config_blk_dev_io_trace=y/m)、规范采集(多核对齐)、精准解析(q→g→i→d→c各阶段),否则无法定位真实i/o瓶颈。

blktrace 不是“开箱即用”的工具,它需要内核支持、正确采集、精准解析三步到位,才能定位到 Q→G→I→D→C 各阶段的真实瓶颈。直接跑 blktrace -d /dev/sda 却看到 Operation not supported,大概率卡在第一步。
确认内核已启用 IO 跟踪支持
多数现代发行版(如 RHEL 8/9、Ubuntu 22.04+、Debian 12)默认关闭 CONFIG_BLK_DEV_IO_TRACE,即使装了 blktrace 包也启动失败。
- 检查命令:
zcat /proc/config.gz | grep CONFIG_BLK_DEV_IO_TRACE(若无/proc/config.gz,改查/boot/config-$(uname -r)) - 期望输出为
=y(编译进内核)或=m(模块),=n或无输出则不支持 - 若为
=m,需先执行sudo modprobe blk_trace;若为=n,无法绕过,只能换内核或重编译 - 云环境(如 AWS EC2 的 NVMe 实例)常禁用该接口,
/sys/block/nvme0n1/trace/目录根本不存在,此时应改用biotop或iosnoop(基于 bpftrace)
规范采集:多核时间戳对齐是关键
blktrace 按 CPU 核心分别记录事件,每个核心的时间戳是本地 cycle counter,彼此不统一。忽略这点会导致把跨核调度抖动误判为 I/O 延迟。
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
- 采集必须开启 all-cpu 模式:
sudo blktrace -d /dev/sda -w 60 -o sda.trace(自动按 CPU 生成sda.trace.0、sda.trace.1等) - 解析时务必显式输出 CPU ID 和纳秒偏移:
blkparse -i sda.trace -f "%5T.%9t %5p %2c %5C %5s %5d ] %5S %5N %5I %5P\n",其中%C是 CPU 编号,%t是纳秒级本地偏移 - 如需映射真实时间,须在采集前后执行
date +%s.%N打标,并结合/proc/uptime推算;不要依赖blkparse -t,它只对单核 trace 可靠
解析与定位:看懂 Q→G→I→D→C 的流转含义
blktrace 事件类型不是缩写游戏,而是内核 tracepoint 的固定命名,每一步都对应块层关键路径:
- Q:IO 进入通用块层队列 —— 可能被合并、重映射(如 LVM/RAID)、限流(如 mq-deadline 调度器)
- G:调度器分配 request 结构体 —— 表示已获取资源,但尚未入队
- I:request 插入设备请求队列 —— 此刻开始受 I/O 调度器管理
- D:request 下发至驱动 —— 跨越软件到硬件边界的动作
- C:设备完成并通知内核 —— D2C 时间反映真实硬件响应能力
常用延迟指标:Q2G 高说明 request 分配慢(可能内存紧张);I2D 高说明调度器积压或队列深度不足;D2C 高则直指硬件或驱动问题(如 NVMe 队列满、RAID 卡固件卡顿)。
进阶分析:用 btt 提取分位数与阶段耗时分布
blkparse 输出仍是原始事件流,真正看瓶颈得靠 btt 做聚合统计:
- 先合并所有 CPU trace:
blkparse -i sda.trace -d sda.blktrace.bin - 生成阶段耗时汇总:
btt -i sda.blktrace.bin -o btt-out,结果中btt-out.avg给出各阶段平均延迟 - 查看 P99/P999 延迟:
btt -l d2c_data -i sda.blktrace.bin > d2c.log,再用脚本排序取分位值(如前 1% 最长的 D2C 时间) - 对比
iostat -x 1中的await与btt的Q2C,若后者显著更高,说明有大量请求在 block layer 外排队(如 page cache 回写阻塞)










