fio磁盘性能压测:参数配置、避坑指南与报告解读

📅 发布时间:2026/10/13 17:50:16
fio磁盘性能压测:参数配置、避坑指南与报告解读
简介fio-3.8.zip 是 FIO 3.8 版本的源代码压缩包FIO 是一款灵活的输入输出压力测试工具常用于评估固态硬盘、机械硬盘、存储阵列及内存文件系统的读写性能。该资源面向存储测试工程师、运维人员和系统调优开发者可用于吞吐量、每秒读写次数、延迟等多维度基准测试。压缩包共包含四百三十三个文件总大小约八百七十二千字节其中包括一百六十四个 C 语言源文件、一百四十八个头文件以及五十八个 fio 配置样例、七个 shell 脚本、六个 job 作业文件和五个 Python 辅助脚本。读者可自行编译生成可执行程序并参考示例搭建顺序读写、随机读写、混合负载等测试场景。目前已有 1643 人学习下载。通过阅读源码和配套脚本能够深入理解 FIO 的配置语法与统计结果在设备选型、系统调优、性能排查等工作中直接复用这些配置节省测试环境搭建时间。1. fio-3.8.zip一套能直接跑的磁盘性能压测工具箱别只拿它当“黑匣子”fioFlexible I/O Tester可能是 Linux 生态里最被低估的磁盘性能测试工具而 fio-3.8.zip 这套资源把编译好的二进制、示例 job 文件和常用脚本打包在了一起省去了从源码编译、依赖折腾的时间。我第一次接触它是在给一批混合硬盘做上线前验收当时用 dd 粗测了几轮数据忽高忽低根本没法形成结论换成 fio 之后才拿到稳定的 IOPS、时延和带宽基线。如果你是运维、存储工程师或者正在评估云盘/物理盘性能fio 几乎是绕不开的标准答案。这篇笔记会带你从 zero 跑出第一份可信的报告把参数含义、脚本模板和那些藏在 performance 数字背后的坑全部拆开最后你会发现它不只是个压测工具更是一套能帮你做容量规划决策的数据来源。2. 先把 fio 的运行模型讲透job 文件、ioengine 和 iodepth 决定了一切2.1 为什么一上来就要理解 job 文件而不只是命令行fio 最常用的两种调用方式是纯命令行参数和 job 文件实际压测时我几乎只用 job 文件。原因很简单命令行参数一旦超过十几个整个命令不仅难读而且容易手抖改错参数。job 文件本质上是一个 ini 风格的配置块一个文件里可以定义多个 job每个 job 可以跑不同的 I/O 负载非常方便做对比测试。一个最简单的 job 文件长这样[global] ioenginelibaio direct1 bs4k rwrandread size1G runtime60 time_based [test1] filename/dev/sdb这里[global]表示全局默认配置[test1]是第一个任务实例。ioengine 指定 I/O 引擎direct1 表示绕过 page cache 直接读写磁盘bs4k 是单次 I/O 块大小rwrandread 是随机读模式size1G 表示测试总数据量runtime60 配合 time_based 表示跑满 60 秒才算完。这个脚本的含义就是用 libaio 引擎在 /dev/sdb 上连续随机读 60 秒每读 4K绕过缓存直接和盘片对话。2.2 libaio、sync、io_uring 怎么选不是越新越好ioengine 的选择会直接影响压测结果的有效性和真实性。fio 里常见的引擎有 sync、libaio、io_uring、pvsync 等其中 sync 是朴素的一次一请求谁发起谁等待几乎模拟不出真实并发。libaio 是异步 I/O在 fio 3.8 时代是主流选择适合模拟数据库这类有很多并发请求的场景。io_uring 是后起之秀但当时不少内核版本支持还不太好而且部分老内核直接跑会报错。我一般在老内核或生产机器上默认用 libaio只有在需要验证某些新特性时才用 io_uring 做对比。对于 SSD 压测libaio 已经足够逼近真实负载了。对于机械盘或者 NFS 这类网络存储则要把iodepth队列深度调小不然测试会失真这个后面展开讲。2.3 iodepth 和 numjobs 的组合折腾了多少人iodepth 是每个 job 的 I/O 队列深度numjobs 是并发 job 数量。两者不是一个概念但经常被混着调。总并发请求数约等于 iodepth × numjobs但要小心 CPU 和内核锁竞争开太多线程反而会降低吞吐。fio --namerandread --ioenginelibaio --iodepth64 --numjobs4 \ --bs4k --direct1 --rwrandread --size1G --runtime60 \ --group_reporting /dev/sdb--group_reporting会把多个 job 的结果合并输出不然你会看到四组独立报告读起来很费劲。--size1G是每个 job 的 I/O 规模四个 job 合计就是 4G如果磁盘剩余空间不够就会直接失败。参数搭配上我一般建议 SSD 用 iodepth32 或 64配合 numjobs4~8而机械盘建议 iodepth8~16numjobs1~2否则会产生很多排队等待数字很难看。3. 自己搭压测脚本顺序写、随机读、混合读写三个模板直接拿走3.1 顺序写模板最容易被 flash 缓存骗到的场景在做 SSD 评测时很多人喜欢先跑一轮顺序写看到 1.5GB/s 的写入带宽就觉得这块盘很快实际上那可能是写入到了 SSD 的 SLC cache一旦 cache 写满速度立刻断崖式下跌。下面这个脚本加入了runtime和time_based可以让写入持续几分钟把缓存打穿之后再观察真实写性能。[global] ioenginelibaio direct1 bs1m rwwrite size10G runtime300 time_based group_reporting [seqwrite] filename/dev/sdb执行命令fio /path/to/seqwrite.fio跑完之后除了关注 BW带宽平均值还要看slat、clat和lat的区别。slat 是提交 I/O 到内核的耗时clat 是从提交到完成的时间lat 是 slat clat。一般情况下 clat 是主要关注点。如果看到 clat 的 p9999% 分位时延远高于平均时延就说明写入过程有突发长尾这在数据库场景下往往是不可接受的。3.2 随机读模板模拟 OLTP 数据库 IO 特征随机读是评估存储系统 QPS 能力最直接的负载。对于模拟 InnoDB 这类数据库引擎的随机读4K 块大小和 32~64 的队列深度比较接近真实场景。注意size要远大于机器可用内存否则页缓存会帮你兜住很多请求测出来的延迟全部失真。[global] ioenginelibaio direct1 bs4k rwrandread size10G runtime120 time_based group_reporting [rr] filename/dev/sdb iodepth32这里每个 job 的队列深度是 32如果单队列无法获得预期 IOPS可以增加 numjobs。常见的做法是直接把numjobs4写进[global]然后把 iodepth 降到 8 或 16让总并发保持不变但这种方式会增加共享锁竞争并非线性提升性能。对比测试时动一个变量就够了两个变量一起动会搞不清楚结果到底受了谁的影响。3.3 混合读写模板读写比例用 rwmixread 控制生产系统很少是纯读或纯写更多是读写混合这时候要用rwrw配合rwmixread来设置读比例。比如 70% 读、30% 写这是在线事务类应用比较典型的分布。[global] ioenginelibaio direct1 bs8k rwrw rwmixread70 size10G runtime120 time_based iodepth32 numjobs4 group_reporting [mix] filename/dev/sdb跑完以后除了看 IOPS还建议把write_lat和read_lat分开解读。混合读写时经常出现读延迟正常、写延迟偏高的情况这不一定说明磁盘写能力差可能是因为写穿透到了更底层。对于 SSD混合读写会触发垃圾回收延迟波动比顺序读写更明显所以建议跑至少 300 秒多观察几个时间片的报告不要只记录 60 秒的数据。3.4 怎么拿到一份足够可信的基线数据压测最怕的是没有对比基准。同一块盘文件系统格式化和裸设备性能差很多分区起始扇区不对齐性能也差很多。我的习惯是每次压测前先记录以下信息测试机器的内核版本、fio 版本、磁盘型号和固件、分区对齐情况、文件系统类型和挂载参数。这些基础信息在出问题排查时特别重要。把上面这些信息写进压测报告的首部才算是一份拿得出手的基线数据。4. 避坑指南我在 fio 压测路上踩过的五个经典坑4.1 测试没跑完直接报错原来是被系统 OOM 杀了现象fio 跑到一半进程消失dmesg里看到Out of memory: Killed process。原因size设置得太大而 fio 的缓存和队列缓冲占用了大量内存任务触发了系统 OOM killer。解决减小size到物理内存的 1/2 以下或者用memory_limited1限制每个 job 的内存使用。再不行就把numjobs降低看看总内存占用情况。4.2 direct1 没写结果测出来的全是 page cache 的速度现象同一块盘测了两次顺序读性能差异好几倍第一次特别快。原因你没加direct1数据先落到页缓存第二次读直接从缓存返回根本没碰到盘。解决凡是压测物理盘direct1几乎必须写。如果确实想测文件系统缓存能力那就明确把缓存作为被测对象而不是给盘下结论。4.3 iodepth 调大后 IOPS 不升反降现象iodepth 从 16 加到 64随机读 IOPS 反而从 9 万多掉到 6 万多。原因队列太深导致 I/O 在设备端排队时间变长甚至触发 SSD 内部调度异常时延上升而吞吐下降。解决从低到高逐档测试iodepth1、4、16、32、64记录每档的 IOPS 和延迟找到拐点。压测不是参数越大越猛而是要找到设备的最优工作点。4.4 runtime 太短根本打不穿 SLC cache现象SSD 顺序写速度显示 2GB/s持续几分钟后掉到 500MB/s。原因短时测试时数据基本都写入到了 SLC 模拟缓存区真实 TLC/QLC 写入速度并没有被暴露。解决顺序写压测 runtime 至少 600 秒或者把size设为磁盘容量的 30% 以上。用fio --status-interval10观察每 10 秒的带宽变化能看到明显的断崖点。4.5 多块盘测试用了同一个 filename 变量现象写了四块盘的压测 job结果四份报告数据几乎一样运行时还有 IO 错误。原因job 文件里没有用${filename}参数四个 job 全写在同一个盘上相当于四倍负载打在同一块盘。解决给每个 job 单独指定filename/dev/sdb、/dev/sdc、/dev/sdd、/dev/sde或者用numjobs搭配filename_format自动生成。5. 看懂 fio 的报告并把它变成决策依据从 IOPS 数值到真实业务评估5.1 三个必须读透的指标IOPS、带宽和时延分位数fio 输出的报告是文本模式的表格化数据每次测试完会显示 read 和 write 两个维度的统计。不要只盯着 IOPS时延分位数才是性能调优的关键。拿随机读的报告举例read: IOPS16220, BW63363KB/s (64.0MB/s)(3802MB/61401msec) read: latencies: mean788.19us, p50720, p901100, p992500, p99.95800前面那行好懂IOPS 是每秒请求数BW 是带宽。后面那行是延迟分位数意思是 50% 的请求在 720us 内完成、90% 在 1100us 内、99% 在 2500us 内、99.9% 在 5800us 内。生产环境看 p99.9 甚至 p99.99因为最慢的几个请求往往就是数据库锁等待和写入放大问题的根源。5.2 拿 fio 结果反推业务容量规划经常遇到的问题是“我这台服务器能扛多少并发用户”其实 fio 不能直接回答这个问题但 fio 数据可以给你反推依据。如果一页数据 8KB每次用户点击平均触发 10 次随机读每个请求需要 1ms那单用户产生的 IOPS 需求大约是 10 次/秒。你的盘 p99 时延是 2ms只要并发超过某个阈值时延就会指数上涨。通过 fio 压测得到的峰值 IOPS 和对应的延迟分位再结合业务模型才能计算合理并发数。这是一个成本低、见效快的容量评估方法。5.3 如何把 fio 结果转成 JSON 自动化收集fio 原生支持--output-formatjson这个功能在自动化压测平台和 CI 环境里特别有用。输出 JSON 之后可以用 jq 或者 Python 解析关键指标。fio --nametest --ioenginelibaio --direct1 --bs4k \ --rwrandread --iodepth32 --size1G --runtime30 \ --output-formatjson result.json之后用 Python 拉取关键字段import json with open(result.json) as f: data json.load(f) jobs data[jobs][0] read jobs[read] print(fIOPS: {read[iops]}) print(fp50: {read[clat_ns][percentile][50.000000] / 1000} us) print(fp99: {read[clat_ns][percentile][99.000000] / 1000} us)clat_ns 里的数值单位是纳秒除以 1000 转成微秒。这种提取方式适合跑完一批机器后批量生成报告。如果想把多台机器的结果汇总对比我一般会把这些字段写入 CSV再让绘图工具生成趋势图这样可以直观看到不同批次机器之间的性能差异还敢让供应商签性能承诺吗有了这几行数据做参照至少你能知道哪些盘值得签哪些盘需要换货。从那以后我每次压测前都会强制自己在 job 文件里写明description日期_场景_盘符并把 JSON 输出固定存到/var/lib/fio-results/方便后续追溯。毕竟压测这种事情记录比结论更值钱。希望这套流程能帮到你。本文还有配套的精品资源点击获取