fio 一个 Linux 磁盘压测工具
官方文档:fio_doc
- 别真的以为人家只支持 Linux,其实官方还有 windows 的安装方法的
安装 fio
安装方法有很多,具体可以参考官方文档,从二进制文件到编译都有,我这边是 rocky linux,可以直接 yum 安装,debian 系列的,可以 apt 安装
yum install -y fio
# 当然,你要用 dnf 也没问题
Job file 的方式
- Job file 格式是经典的 ini 文件,其中 [] 括号中的名称定义 job 名称。
- 您可以随意使用任何您想要的 ASCII 名称,但具有特殊含义的 global 除外。
- job 名称后面是零个或多个参数的序列,每行一个参数,用于定义 job 的行为。
- 如果一行中的第一个字符是
;
或#
,则整行将作为注释丢弃。创建一个 Job file ,内容类似下面这样,这是同时开启随机读写的两个任务
[global]
# 使用异步 I/O 引擎
ioengine=libaio
# 启动 4 个并发工作线程
numjobs=4
# 随机读写
rw=randrw
# 块大小
bs=4k
# 每个线程测试文件的大小
size=1G
# 运行时间,不写单位表示秒
runtime=60
# 基于时间的测试
time_based
# 汇总报告
group_reporting
[randrw_test]
# 测试文件路径
filename=/tmp/randrw_testfile
ioengine
:linux 下的异步引擎,其他的,详见官方文档
read
:顺序读取write
:顺序写入trim
:顺序修剪(仅限 Linux 块设备和 SCSI 字符设备)randread
:随机读取randwrite
:随机写入randtrim
:随机修剪(仅限 Linux 块设备和 SCSI 字符设备)rw,readwrite
:顺序混合读取和写入randrw
:随机混合读取和写入trimwrite
:顺序 trim+write 序列。
- 首先修剪块,然后写入相同的块。因此,如果指定了io_size=64K,则 Fio 将修剪总共 64K 字节,并在相同的修剪块上写入 64K 字节。此行为将与 number_ios 或其他限制总字节数或 I/O 数量的 Fio 选项一致。
randtrimwrite
:与 trimwrite 类似,但使用随机偏移量而不是顺序写入blocksize=int[,int][,int], bs=int[,int][,int]
- block 块的大小,默认是 4096
bs=256k
:表示 256k 用于读取、写入和修剪bs=8k,32k
:表示 8k 用于读取,32k 用于写入和 trimbs=8k,32k,
:表示 8k 用于读取,32k 用于写入,默认用于修剪bs=,8k
:表示 default 表示读取,8k 表示写入和 trimbs=,8k,
:表示 default 表示读取,8k 表示写入,default 表示 trims
runtime
:指定 fio 运行多长时间后停止time_based
:fio 基于时间测试,即使文件达到 size 的大小,也不会听,直到 runtime 到了- 还有更多其他的,可以继续看官方文档
运行 fio
fio disk-test.fio
输出的结果
randrw_test: Laying out IO file (1 file / 1024MiB)
Jobs: 4 (f=4): [m(4)][100.0%][r=22.4MiB/s,w=23.0MiB/s][r=5745,w=5889 IOPS][eta 00m:00s]
randrw_test: (groupid=0, jobs=4): err= 0: pid=23995: Mon Oct 28 15:54:54 2024
read: IOPS=10.0k, BW=39.2MiB/s (41.1MB/s)(2352MiB/60002msec)
slat (nsec): min=1614, max=1209.4M, avg=198081.45, stdev=2970772.65
clat (nsec): min=615, max=107632, avg=1949.24, stdev=1541.66
lat (usec): min=2, max=1209.4k, avg=200.56, stdev=2970.90
clat percentiles (nsec):
| 1.00th=[ 748], 5.00th=[ 788], 10.00th=[ 924], 20.00th=[ 956],
| 30.00th=[ 996], 40.00th=[ 1704], 50.00th=[ 1912], 60.00th=[ 2096],
| 70.00th=[ 2224], 80.00th=[ 2384], 90.00th=[ 2768], 95.00th=[ 3504],
| 99.00th=[ 6240], 99.50th=[12352], 99.90th=[18304], 99.95th=[23424],
| 99.99th=[33536]
bw ( KiB/s): min= 2211, max=85120, per=100.00%, avg=40941.17, stdev=3783.36, samples=468
iops : min= 551, max=21280, avg=10235.14, stdev=945.87, samples=468
write: IOPS=10.1k, BW=39.3MiB/s (41.2MB/s)(2356MiB/60002msec); 0 zone resets
slat (usec): min=2, max=1210.1k, avg=191.73, stdev=2620.78
clat (nsec): min=633, max=201793, avg=1228.79, stdev=1118.42
lat (usec): min=2, max=1210.1k, avg=193.16, stdev=2620.95
clat percentiles (nsec):
| 1.00th=[ 756], 5.00th=[ 804], 10.00th=[ 828], 20.00th=[ 932],
| 30.00th=[ 996], 40.00th=[ 1012], 50.00th=[ 1032], 60.00th=[ 1048],
| 70.00th=[ 1096], 80.00th=[ 1256], 90.00th=[ 1704], 95.00th=[ 2064],
| 99.00th=[ 4128], 99.50th=[ 6688], 99.90th=[16192], 99.95th=[18560],
| 99.99th=[27776]
bw ( KiB/s): min= 2337, max=85032, per=100.00%, avg=41016.50, stdev=3789.15, samples=468
iops : min= 582, max=21258, avg=10253.91, stdev=947.31, samples=468
lat (nsec) : 750=0.98%, 1000=30.75%
lat (usec) : 2=42.40%, 4=23.76%, 10=1.61%, 20=0.45%, 50=0.06%
lat (usec) : 100=0.01%, 250=0.01%
cpu : usr=1.92%, sys=5.34%, ctx=812754, majf=1, minf=66
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=602052,603252,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: bw=39.2MiB/s (41.1MB/s), 39.2MiB/s-39.2MiB/s (41.1MB/s-41.1MB/s), io=2352MiB (2466MB), run=60002-60002msec
WRITE: bw=39.3MiB/s (41.2MB/s), 39.3MiB/s-39.3MiB/s (41.2MB/s-41.2MB/s), io=2356MiB (2471MB), run=60002-60002msec
Disk stats (read/write):
dm-0: ios=361023/500039, merge=0/0, ticks=47002/484395, in_queue=531397, util=99.83%, aggrios=361930/500891, aggrmerge=0/25630, aggrticks=47194/467630, aggrin_queue=514825, aggrutil=99.83%
vda: ios=361930/500891, merge=0/25630, ticks=47194/467630, in_queue=514825, util=99.83%
输出报告
输出的报告解释:Interpreting the output
# read/write/trim:IOPS 是每秒执行的平均 I/O;BW 是平均带宽速率
write: IOPS=10.1k, BW=39.3MiB/s (41.2MB/s)(2356MiB/60002msec); 0 zone resets
# 提交延迟,min 是最小值,max 是最大值,avg 是平均值,stdev 是标准偏差
slat (usec): min=2, max=1210.1k, avg=191.73, stdev=2620.78
# 完成延迟,从提交到 I/O 部分完成的时间
clat (nsec): min=633, max=201793, avg=1228.79, stdev=1118.42
# 总延迟,这表示从 fio 创建 I/O 单元到 I/O 操作完成的时间。它是提交和完成延迟之和
lat (usec): min=2, max=1210.1k, avg=193.16, stdev=2620.95
clat percentiles (nsec):
| 1.00th=[ 756], 5.00th=[ 804], 10.00th=[ 828], 20.00th=[ 932],
| 30.00th=[ 996], 40.00th=[ 1012], 50.00th=[ 1032], 60.00th=[ 1048],
| 70.00th=[ 1096], 80.00th=[ 1256], 90.00th=[ 1704], 95.00th=[ 2064],
| 99.00th=[ 4128], 99.50th=[ 6688], 99.90th=[16192], 99.95th=[18560],
| 99.99th=[27776]
# 基于离散间隔测量值的带宽统计信息
bw ( KiB/s): min= 2337, max=85032, per=100.00%, avg=41016.50, stdev=3789.15, samples=468
# 基于离散间隔测量值的 IOPS 统计信息
iops : min= 582, max=21258, avg=10253.91, stdev=947.31, samples=468
# I/O 完成延迟的分布,这是从 I/O 离开 fio 到完成的时间
lat (nsec) : 750=0.98%, 1000=30.75%
lat (usec) : 2=42.40%, 4=23.76%, 10=1.61%, 20=0.45%, 50=0.06%
lat (usec) : 100=0.01%, 250=0.01%
# CPU 使用率
cpu : usr=1.92%, sys=5.34%, ctx=812754, majf=1, minf=66
# 作业生命周期内 I/O 深度的分布
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
# 在单个提交调用中提交的 I/O 块数
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
# 与上面的提交编号类似,但用于完成
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
# 发出的读 / 写 / 修剪请求数,以及其中有多少请求是短的或丢弃的
issued rwts: total=602052,603252,0,0 short=0,0,0,0 dropped=0,0,0,0
# 这些值适用于 latency_target 和相关选项。启用这些选项时,本节介绍满足指定延迟目标所需的 I/O 深度。
latency : target=0, window=0, percentile=100.00%, depth=1
组统计信息
Run status group 0 (all jobs):
READ: bw=39.2MiB/s (41.1MB/s), 39.2MiB/s-39.2MiB/s (41.1MB/s-41.1MB/s), io=2352MiB (2466MB), run=60002-60002msec
WRITE: bw=39.3MiB/s (41.2MB/s), 39.3MiB/s-39.3MiB/s (41.2MB/s-41.2MB/s), io=2356MiB (2471MB), run=60002-60002msec
bw
:此组中线程的聚合带宽,后跟此组中所有线程的最小和最大带宽。括号外的值是 2 的幂格式,括号内的值是 10 的幂格式的等效值io
:此组中所有线程执行的聚合 I/O。格式与 bw 相同run
:此组中线程的最小和最长运行时间
磁盘统计信息
Disk stats (read/write):
dm-0: ios=361023/500039, merge=0/0, ticks=47002/484395, in_queue=531397, util=99.83%, aggrios=361930/500891, aggrmerge=0/25630, aggrticks=47194/467630, aggrin_queue=514825, aggrutil=99.83%
vda: ios=361930/500891, merge=0/25630, ticks=47194/467630, in_queue=514825, util=99.83%
ios
:所有组执行的 I/O 数sectors
:所有组传输的数据量(以 512 字节为单位)merge
:I/O 调度程序执行的合并数ticks
:我们让磁盘忙碌的时钟周期数in_queue
:在磁盘队列中花费的总时间util
:磁盘利用率。值为 100% 表示我们使磁盘始终处于繁忙状态,50% 表示磁盘有一半的时间处于空闲状态
环境变量的方式
主要也是和 job file 配合使用,这里就不多做演示了,可以直接看上面的官方文档链接
命令行的方式
- 以下内容和上面 job file 的是一样的
fio --name=randrw \
--ioengine=libaio \
--rw=randwrite \
--bs=4k \
--size=1G \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting \
--filename=/tmp/randrw_testfile