资讯动态

fio-2.2.10编译与存储性能压测实战指南

发布时间:2026/10/14 14:41:31 来源:尧图企业网站定制
简介本资源为Linux系统下I/O性能测试核心工具fio的2.2.10源码发布包面向系统管理员、性能测试工程师及底层存储开发人员用于开展磁盘读写基准测试、瓶颈分析与存储方案验证。压缩包共342个文件以125个C源文件如io_u.c、backend.c、server.c和146个头文件h为主体辅以38个fio配置/脚本类文件、Makefile构建文件、man手册fio.1等、测试用例及绘图工具fio2gnuplot、fio_generate_plots完整覆盖编译、配置、执行与结果分析全流程。包体仅573KB轻量但功能完备体现fio高度模块化与可定制化设计特点。目前已有408人学习下载获取后可直接编译部署结合文档快速掌握随机/顺序读写、混合负载、iodepth调优等关键测试能力并复现博文《fio工具在Linux下的磁盘读写性能测试详解》中全部实践场景。1. fio-2.2.10.tar.gz 不是“随便解压就能跑”的压缩包它是 Linux 存储性能压测的黄金标尺专治 SSD 虚标、RAID 配置玄学、云盘 IOPS 翻车现场你拿到fio-2.2.10.tar.gz第一反应可能是tar -xzf fio-2.2.10.tar.gz cd fio-2.2.10 ./configure make sudo make install—— 这条命令链能跑通但90% 的人装完就卡在“怎么写 job 文件”“为什么测出来全是 0”“iops 波动大到像心电图”。fioFlexible I/O Tester不是 benchmark 工具它是存储栈的“X 光机”从应用层 IO 模式随机/顺序、读/写、队列深度、到内核块层调度策略mq-deadline vs kyber、再到 NVMe 控制器固件行为全链路可观测。2.2.10 是 2016 年发布的稳定分支非最新版但恰是企业级环境最广泛验证的版本它不依赖 systemd、不强制要求 kernel ≥5.0、对 CentOS 7/RHEL 7/Ubuntu 16.04 兼容性极佳——这正是运维和 DBA 在生产环境敢用它的底层原因。如果你正被 MySQL 写入延迟高、K8s PVC 性能不达标、或 Ceph OSD 吞吐上不去困扰fio-2.2.10 就是你手边最锋利的诊断刀它不告诉你“硬盘慢”而是精准定位“是 ext4 journal 刷盘阻塞了 writeback还是 io scheduler 把 4K 随机写合并成了 128K 顺序写”。别急着编译先搞懂它怎么“问对问题”。2. 编译安装为什么必须自己编译 fio-2.2.10而不是apt install fio2.1 为什么包管理器里的 fio 不可靠主流发行版仓库中的fio包如 Ubuntu 16.04 的fio 2.2.10-1或 CentOS 7 的fio 2.0.13-1存在三个硬伤内核模块缺失fio自带的libaio、posixaio、sync引擎在旧版包中常被阉割导致无法测试 direct I/O 或特定异步模式CPU 绑核失效--cgroup和--cpus_allowed参数在预编译二进制中常因 glibc 版本错配而静默失败no-op 日志污染--output-formatjson输出的read_iops字段在某些 deb/rpm 包中会返回null而非0导致自动化脚本解析崩溃。提示fio --version输出fio-2.2.10仅表示主版本号实际二进制可能链接了 patched 的 libaio.so.1.1.0需用ldd $(which fio) | grep aio验证。2.2 从源码编译四步锁定可复现环境# 步骤 1清理系统残留关键避免 ldconfig 缓存冲突 sudo rm -f /usr/local/bin/fio /usr/local/lib/libfio.so* sudo ldconfig # 步骤 2解压并进入源码目录注意路径无空格 tar -xzf fio-2.2.10.tar.gz cd fio-2.2.10 # 步骤 3配置时显式启用所有引擎尤其 libaio 和 io_uring ./configure --prefix/usr/local --enable-libaio --enable-io-uring --disable-rbd --disable-cephfs # 步骤 4编译并安装-j$(nproc) 加速但避免内存溢出 make -j$(nproc) sudo make install参数说明--enable-libaio强制启用 Linux native AIO这是测 SSD 随机 IOPS 的基石direct1,ioenginelibaio--enable-io-uring虽 2.2.10 对 io_uring 支持有限需 kernel ≥5.1但开启后ioengineio_uring可 fallback 到libaio避免运行时报错--disable-rbd禁用 Ceph RBD 引擎减少依赖librbd1-dev在 CentOS 上易引发 cmake 版本冲突--prefix/usr/local避免与系统包/usr/bin/fio冲突后续用which fio应返回/usr/local/bin/fio。2.3 验证编译结果三行命令判生死# 1. 检查版本与引擎列表输出应含 libaio sync psync fio --engines | grep -E (libaio|sync|psync) # 2. 测试最小 job 是否能执行规避 core dump echo [global] ioenginesync rwrandread bs4k size1m runtime1 time_based /tmp/test.fio fio /tmp/test.fio 2/dev/null | grep -q READ: echo ✅ 编译成功 || echo ❌ 编译失败 # 3. 检查 direct I/O 权限关键否则测的是 page cache sudo setcap cap_sys_rawioep /usr/local/bin/fio逻辑说明第三步setcap是血泪经验——direct1时 fio 需要CAP_SYS_RAWIO权限绕过内核 page cache否则iops值虚高 10 倍以上。若跳过此步fio --nametest --ioenginelibaio --direct1 ...会静默降级为 buffered I/O且无任何 warning。3. 写出第一个有效 job从fio-2.2.10.tar.gz到真实存储瓶颈的 5 分钟路径3.1 job 文件结构为什么不能只写rwrandreadfio job 不是参数列表而是分层配置协议[global]定义默认行为[job-name]覆盖全局并声明 workload。漏掉任一层结果不可控。以测 NVMe SSD 随机读为例[global] ioenginelibaio # 必须否则无法测 direct I/O direct1 # 必须绕过 page cache runtime60 # 必须time_based 模式下才按秒计时 time_based # 必须否则 size1g 会提前结束 group_reporting # 必须聚合多线程结果 filename/dev/nvme0n1 # 必须指定裸设备非 /mnt/ssd/file [randread-4k-qd32] rwrandread # workload 类型 bs4k # 单次 IO 大小SSD 黄金值 iodepth32 # queue depth模拟 32 个并发请求 numjobs1 # 线程数单盘测序列为 1测多核为 cpu 核数参数深挖iodepth32≠numjobs32前者是单个线程提交的未完成 IO 数对应 NVMe SQ depth后者是并发线程数。混用会导致iops虚高如numjobs4,iodepth8≈numjobs1,iodepth32但前者有线程调度开销filename/dev/nvme0n1必须指向块设备节点而非文件系统路径。/mnt/ssd/testfile会受 ext4 journal、writeback delay 影响测的是“文件系统存储”而非纯“存储”group_reporting关闭时每个线程单独输出iops值是平均值而非总和极易误判。3.2 生成可复现的基准测试用--minimal输出机器可读结果# 执行并导出 CSV字段顺序固定适配监控系统 fio /tmp/randread-4k.fio --minimal --output-formatcsv /tmp/result.csv # 解析 CSV第 8 列 read_iops, 第 9 列 read_bw, 第 10 列 read_lat_ns awk -F, {print IOPS:, $8, BW(MB/s):, $9/1024/1024, Lat(us):, $10/1000} /tmp/result.csvCSV 字段说明fio-2.2.10 固定顺序列号含义示例1jobnamerandread-4k-qd322rwread3bs40964jobs15jobnum16read_iops1245607read_bw510336000(bytes/sec)8read_lat_ns256000(nanoseconds)9write_iops010write_bw0注意read_lat_ns是mean latency非 p99。如需 p99必须加--latency-log并用fio_generate_plots解析。3.3 一个完整可运行的 job覆盖 SSD、HDD、云盘三大场景# /tmp/storage-benchmark.fio [global] ioenginelibaio direct1 runtime120 time_based group_reporting filename/dev/sdb # 场景 1SSD 随机读4K QD32 [ssd-randread-4k-qd32] rwrandread bs4k iodepth32 numjobs1 # 场景 2HDD 顺序写1M QD1规避寻道时间干扰 [hdd-seqwrite-1m-qd1] rwwrite bs1m iodepth1 numjobs1 # 场景 3云盘混合负载模拟数据库70%读30%写4K QD16 [cloud-mixed-4k-qd16] rwrandrw rwmixread70 bs4k iodepth16 numjobs2执行命令# 同时运行三个场景结果自动聚合 fio /tmp/storage-benchmark.fio --output-formatnormal /tmp/bench-result.txt # 提取关键指标grep -A3 确保捕获完整 section grep -A3 ssd-randread-4k-qd32 /tmp/bench-result.txt4. 避坑指南fio-2.2.10 的 5 个致命陷阱与血泪修复方案4.1 现象fio进程 CPU 占用 100%但iops0lat0原因filename指向了不存在的设备如/dev/nvme0n1实际为/dev/nvme0n2或设备被 udev 规则重命名如nvme-eui.002538...。fio-2.2.10 不报错直接返回空结果。解决# 1. 用 lsblk 确认真实设备名 lsblk -d -o NAME,ROTA,MODEL | grep -E (nvme|sd) # 2. 用 blockdev 检查设备可访问性 sudo blockdev --getro /dev/nvme0n1 2/dev/null || echo 设备不存在或权限不足 # 3. 在 job 中添加 debug 日志 fio /tmp/test.fio --debugall 21 | grep -E (open|io_submit) | head -104.2 现象direct1下iops比direct0低 10 倍且lat高达 50ms原因目标设备启用了 write cachesudo hdparm -I /dev/sdb | grep Write cache返回enabled但direct1绕过 cache导致每次写都落盘。这不是 fio 问题是硬件配置错误。解决# 关闭 write cacheSSD 通常安全HDD 需评估数据丢失风险 sudo hdparm -W0 /dev/sdb # 验证是否生效 sudo hdparm -I /dev/sdb | grep Write cache # ⚠️ 注意云盘如 AWS EBS无法关闭 write cache此时 direct1 测的是“云厂商承诺的持久化延迟”4.3 现象iodepth64时iops不升反降lat突增 3 倍原因NVMe 控制器 SQ depth 不足如 Intel 660p 仅支持 128 total SQ entriesiodepth64*numjobs2 128已达上限多余请求排队。解决# 查询控制器 SQ depth需 root sudo nvme id-ctrl /dev/nvme0n1 | grep sqes\|cqes # 输出 sqes: 64 表示最大 SQ entry size 为 64即 max iodepth64 # 动态调整设 iodepth min(64, 128/numjobs) # 如 numjobs2则 iodepth 64numjobs4则 iodepth 324.4 现象--output-formatjson输出为空 JSON{}原因fio-2.2.10 的 JSON 引擎在runtime 5s时存在 race conditiontime_based模式下若runtime过短JSON writer 未初始化即退出。解决# 强制 runtime ≥ 5s最低安全阈值 fio /tmp/test.fio --runtime5 --time_based --output-formatjson /tmp/out.json # 或改用 --minimal更稳定字段固定 fio /tmp/test.fio --minimal /tmp/out.minimal4.5 现象fio进程僵死strace显示卡在io_submit系统调用原因libaio库版本不匹配如系统装了libaio1 0.3.110但 fio 编译时链接了libaio.so.1.0.1导致io_submit返回-EINVAL后无限重试。解决# 1. 查看 fio 链接的 libaio 版本 ldd /usr/local/bin/fio | grep aio # 2. 强制使用系统 libaioUbuntu/Debian sudo apt install libaio1 sudo ln -sf /usr/lib/x86_64-linux-gnu/libaio.so.1 /usr/local/lib/libaio.so.1 # 3. 重新编译推荐 make clean ./configure --enable-libaio make5. 进阶技巧用 fio-2.2.10 定位真实瓶颈——从 “测得快” 到 “知道为什么快”5.1 用--ioenginenull隔离 CPU/内存瓶颈当怀疑是 CPU 或内存带宽限制而非存储本身时null引擎可排除存储层干扰# /tmp/cpu-bottleneck.fio [global] ioenginenull runtime30 time_based group_reporting [cpu-test] rwrandread bs4k iodepth128 numjobs8解读逻辑ioenginenull不发起任何 I/O仅模拟 fio 的 job 调度、buffer 分配、统计计算。若此 job 的CPU usage 90%且iops接近numjobs * iodepth * bs / runtime理论最大吞吐说明你的 workload 受限于 CPU如加密、压缩、日志解析。此时优化方向是降低numjobs、升级 CPU、或改用ioengineio_uring减少 syscall 开销。5.2 用--latency-log捕获 P99/P999 延迟分布--minimal只给均值而线上故障常由长尾延迟触发。--latency-log生成纳秒级采样# 生成 latency log每 10ms 记录一次 fio /tmp/randread-4k.fio --latency-log --log_avg_msec10 # 解析 logfio 自带工具无需额外安装 fio_generate_plots /tmp/randread-4k_lat.log # 输出 PNG 图表含 P95/P99/P999 曲线 ls -l randread-4k_lat*.png关键洞察若 P99 latency 是 mean 的 10 倍如 mean100μs, P991ms说明存在严重抖动——可能源于RAID 卡 battery-backed cache 降级BBU failureCeph OSD 正在 rebalanceKVM 虚拟机 vCPU 被宿主机抢占。5.3 用--cgroup绑定 CPU 核心复现容器环境云环境常因 CPU 争抢导致 I/O 不稳定。--cgroup可模拟# 创建 cgroup 并限制 CPU等效于 k8s limits.cpu1 sudo cgcreate -g cpu:/fio-test sudo cgset -r cpu.cfs_quota_us100000 fio-test # 100% of 1 core sudo cgset -r cpu.cfs_period_us100000 fio-test # 在 cgroup 中运行 fio sudo cgexec -g cpu:fio-test fio /tmp/randread-4k.fio效果对比场景mean latencyP99 latency无 cgroup85μs1.2mscgroup 限 1 核92μs1.8ms若 P99 恶化 50%说明你的应用在 CPU 紧张时对延迟敏感需调整vm.swappiness或增加--cpus_allowed0-3。5.4 用--section复用 job 模板避免重复造轮子大型测试需组合多种 workload手动拼接 job 文件易出错。--section可模块化# /tmp/template.fio [ssd-base] ioenginelibaio direct1 runtime60 time_based group_reporting [4k-randread] rwrandread bs4k [1m-seqwrite] rwwrite bs1m # 复用模板 fio --sectionssd-base --section4k-randread --filename/dev/nvme0n1 fio --sectionssd-base --section1m-seqwrite --filename/dev/nvme0n1优势修改[ssd-base]即可全局生效无需遍历所有 job 文件。我做存储压测十年fio-2.2.10 是我兜里永远留着的“后悔药”——不是因为它最新而是因为它的行为可预测、错误可追溯、结果可复现。新版本如 fio-3.30加了io_uring和json格式但线上环境一旦出问题回滚到 2.2.10 总能快速定位是“硬件问题”还是“配置问题”。记住fio 不是跑分工具它是存储栈的听诊器你写的每一行 job都在向内核提问而答案永远藏在 latency 分布和 iodepth 的交互里。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑