Linux fio 的随机读写测试与 IOPS / 延迟曲线绘制脚本

1次阅读

fio随机读写测试需加–direct=1绕过page cache、–iodepth控制队列深度、–bs=4k测iops,配–time_based–runtime=60和–size=10g防缓存干扰;输出曲线须用–write_iops_log与–write_lat_log生成时序日志,再清洗绘图。

Linux fio 的随机读写测试与 IOPS / 延迟曲线绘制脚本

fio 随机读写测试命令怎么写才不跑偏

直接用 fio 跑随机读写,十次有八次测出来的是缓存数据或队列积结果,不是磁盘真实能力。关键在绕过 page cache、控制队列深度、固定 IO size 和模式。

  • 必须加 --direct=1,否则 linux 会把大部分 IO 拦在 page cache 里,randread 可能全走内存
  • --iodepth=32 模拟高并发场景,但别盲目堆高——NVMe 盘可设到 64,SATA SSD 超过 16 就容易掩盖延迟差异
  • --bs=4k 是测 IOPS 的黄金值;想看吞吐就换 --bs=128k--bs=1m,但两者不能混在同一轮测试比
  • --time_based --runtime=60,避免因文件大小不足提前退出;同时配 --size=10g(至少 2 倍于 RAM)防 swap 干扰

怎么让 fio 输出能直接画 IOPS 和延迟曲线

fio 默认输出是人眼友好型汇总,没法直接喂给 gnuplot 或 pandas。得靠 --output-format=json + 后处理,但注意默认 JSON 不含逐秒明细。

  • --write_iops_log=iops --write_lat_log=lat --log_avg_msec=1000,生成两个日志:每秒平均 IOPS 和每秒平均延迟(单位微秒)
  • 生成的 iops.log 是纯文本,三列:时间戳、IOPS、带宽(KB/s);lat.log 第三列是延迟(微秒),别误当成毫秒
  • 如果要亚秒级分辨率(比如看 burst 行为),把 --log_avg_msec=1000 改成 100,但日志体积暴涨,SSD 测 60 秒可能出 600 行
  • 别用 --minimal 输出——它压根不记录时间序列,只给最终均值

gnuplot 绘制延迟曲线时常见坐标错乱

直接用 lat.log 画图,经常发现 X 轴是乱序时间戳、Y 轴数值跳变巨大,其实是 log 文件里有空行或头尾非数据行。

  • 先清洗:grep -v "^#" lat.log | awk '$3 > 0 && $3 lat_clean.dat(过滤掉注释、异常大延迟)
  • gnuplot 中 Y 轴建议用对数刻度:set logscale y,因为随机读延迟常跨 3 个数量级(几十μs 到几 ms)
  • 如果用 smooth csplines 插值,会平滑掉真实毛刺;真要看瞬时抖动,就用 with lines 原样连点
  • 别漏掉单位标注:set ylabel "Latency (μs)",μ 是 μ,不是 u 或 mu

线程/多 job 下 IOPS 算术叠加为什么不准

两个 --numjobs=4 的 job 并发跑,总 IOPS 不是单个 job 的 2 倍——尤其在 SATA 盘或低队列深度下,控制器争抢会让实际吞吐塌缩。

  • 验证方法:分别跑 --numjobs=124,看 IOPS 是否线性增长;若 4 线程只比 2 线程高 10%,说明瓶颈在硬件层
  • --group_reporting 必须开启,否则每个 job 单独输出,sum 时容易漏算或重复算
  • 混合读写(--rw=randrw --rwmixread=70)时,fio 默认按字节比例混合,但 IOPS 计算仍分读/写两列,别直接加总
  • --name 给每个 job 打标,比如 --name=read-4k-qd32,否则多个 job 日志混在一起根本分不清谁是谁

真正难的不是跑出数字,而是让每次测试的变量可控——同一块盘,换一个 --ioengine(比如 libaio vs sync),延迟分布可能完全两样,但很多人根本没意识到自己在测引擎而非磁盘。

text=ZqhQzanResources