一、概述
FIO 是一个开源的主流的 Linux 磁盘 IO 测试工具,可模拟各种 IO workload,广泛用于 benchmark、QA、验证等场景,支持多达19种 IO engines(如:libaio, sync等),并支持多种操作系统,如:Linux、Windows。通常对于磁盘的测试主要会关注这几个测试项,分别是:Iops,也就是每秒进行读写(I/O)操作的次数,它评估的是,每秒对于磁盘的操作次数和能力,执行次数越多说明执行数据越快。
另外一个指标就是对磁盘的吞吐率,它表示每秒对于磁盘的读写数据量,单位为 MB/s,数值越高表示读写数据越多。
第三个指标就是读写延迟,表示单个 IO 去写磁盘,做一次 IO 操作的耗时是多少。
我们使用 FIO 这个工具可以针对这三项指标去进行测试,并分析结论,在使用 FIO 之前建议你尽量使用一台空闲的机器来运行,以免因为 FIO 对操作系统上的磁盘或者文件的读写而损坏文件系统,这个地方你需要注意一下。
二、安装
有两种方式安装fio,binary 安装和 source 安装,本文使以Binary的方式安装。
2.1 下载rpm进行安装
从官网上下载Redhat系统所对应的3.1-1.el7版本。访问方式如下:
https://github.com/axboe/fio -> https://apps.fedoraproject.org/packages/fio -> 3.1-1.el7
选择“fio-3.1-1.el7.x86_64.rpm”二进制软件包进行下载。
2.2 yum直接安装
另外也可以直接从yum方式进行安装,yum install fio
[root@CNSZ036811 ~]# fio -v
fio-3.1
三、基础概念
在讲解 fio 之前,有必要了解一些其中涉及到的基础概念。
IO 类型(IO pattern):指读写方式,顺序、随机两种。
块大小:上层应用读写数据时的最小逻辑存储单元,如:4KB,1MB。磁盘性能测试过程,衡量 IOPS 时,通常采用小块数据随机读写(如:4K >= 块大小 <=32K 块大小),而衡量吞吐量时,通常采用大块数据顺序读写(如:64K >= 块大小 <= 1M)。
IO 大小:每次 IO 请求需要读写的数据大小。
IO 引擎:作业读写 IO 的方式,即以特定方式来访问存储文件。每种IO引擎有其自身的使用场景。
线程数:默认情况下是使用 fork 创建进程的方式来运行作业,但开销较大,因此通常情况,会指定 -thread 参数以线程方式测试。
队列深度:队列深度指系统中等待处理的 IO 请求的数目。队列深度的值决定了应用程序可以让多个 IO 操作排队供磁盘处理。
四、FIO 体验
了解了这些基本概念后,我们开始 fio 体验之旅。我们先来运行一个最简单的命令来感受一下 fio。
[root@cnsz036814 ~]# fio -filename=/dev/rbd0 -name=mytest
mytest: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
fio-3.1
Starting 1 process
Jobs: 1 (f=1): [f(1)][100.0%][r=273MiB/s,w=0KiB/s][r=69.9k,w=0 IOPS][eta 00m:00s]
mytest: (groupid=0, jobs=1): err= 0: pid=3367325: Thu Apr 4 14:30:31 2019
read: IOPS=26.5k, BW=103MiB/s (108MB/s)(10.0GiB/99102msec)
clat (nsec): min=1042, max=528258k, avg=37415.13, stdev=2331215.59
lat (nsec): min=1087, max=528258k, avg=37464.12, stdev=2331215.58
clat percentiles (nsec):
| 1.00th=[ 1160], 5.00th=[ 1192], 10.00th=[ 1208],
| 20.00th=[ 1240], 30.00th=[ 1256], 40.00th=[ 1304],
| 50.00th=[ 1368], 60.00th=[ 1448], 70.00th=[ 1496],
| 80.00th=[ 1592], 90.00th=[ 1768], 95.00th=[ 1992],
| 99.00th=[ 2576], 99.50th=[ 3504], 99.90th=[ 35584],
| 99.95th=[ 5406720], 99.99th=[119013376]
bw ( KiB/s): min= 8192, max=1136744, per=99.01%, avg=104755.10, stdev=208227.89, samples=198
iops : min= 2048, max=284186, avg=26188.71, stdev=52057.00, samples=198
lat (usec) : 2=95.25%, 4=4.31%, 10=0.22%, 20=0.09%, 50=0.03%
lat (usec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2=0.03%, 4=0.01%, 10=0.01%, 20=0.01%, 50=0.01%
lat (msec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%
cpu : usr=1.94%, sys=4.69%, ctx=2328, majf=0, minf=62
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 rwt: total=2621440,0,0, short=0,0,0, dropped=0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: bw=103MiB/s (108MB/s), 103MiB/s-103MiB/s (108MB/s-108MB/s), io=10.0GiB (10.7GB), run=99102-99102msec
Disk stats (read/write):
rbd0: ios=3741/0, merge=7487/0, ticks=428805/0, in_queue=428827, util=99.12%
在这个命令中,我们指定了一个非常简单的参数组合,仅包括被测 rbd 设备(/dev/rbd0),以及 job 的名字(mytest)两个参数,但是 fio 仍然能够正常运行,并输出测试结果,这两个参数组合是 fio 运行时所需要显式指定的最小参数组合。当然,fio 在运行时不止会使用这两个参数,其他未指定的但运行时所必要的参数,fio 会使用其默认值。
接下来,我们来了解一下输出的测试结果的含义,我会将其分为几个部分来讲解,若运行更为复杂的 fio 命令,输出也大同小异。
Part 1:
mytest: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
作业概况,含义如下:
mytest:指定的作业名字。
g=0:该作业属于 group 0。
rw=read: 默认的 io pattern 是顺序读。
bs:分别表示用于 read/write/trim 的块大小,默认是4K。
ioengine=sync,默认 IO 引擎是psync。
iodepth=1:队列深度默认为1,表明设备上正在运行的 IO unit 数量不超过 1。
Part 2:
Jobs: 1 (f=1): [f(1)][100.0%][r=273MiB/s,w=0KiB/s][r=69.9k,w=0 IOPS][eta 00m:00s]
显示创建的job的状态,字段含义如下:
Jobs: 1:表示定义的作业,此处只定义了一个,也即进程数。
(f=1):表示当前打开的文件数量
[R(1)]:表示该作业当前状态,此处表示运行,顺序读
[100.0%]:表示该作业预估完成的百分比,此处表示 100% 结束。
接下来,显示了 IO 速率,分别指(读/写/trim)带宽和 IOPS,其中trim是可选项。
Part 3
mytest: (groupid=0, jobs=1): err= 0: pid=3367325: Thu Apr 4 14:30:31 2019
作业名字以及作业相关信息,比如:group id,作业数(jobs=1),作业完成时间。
err= 0:作业运行过程,no errors happened。
Part 4
read: IOPS=26.5k, BW=103MiB/s (108MB/s)(10.0GiB/99102msec)
clat (nsec): min=1042, max=528258k, avg=37415.13, stdev=2331215.59
lat (nsec): min=1087, max=528258k, avg=37464.12, stdev=2331215.58
clat percentiles (nsec):
| 1.00th=[ 1160], 5.00th=[ 1192], 10.00th=[ 1208],
| 20.00th=[ 1240], 30.00th=[ 1256], 40.00th=[ 1304],
| 50.00th=[ 1368], 60.00th=[ 1448], 70.00th=[ 1496],
| 80.00th=[ 1592], 90.00th=[ 1768], 95.00th=[ 1992],
| 99.00th=[ 2576], 99.50th=[ 3504], 99.90th=[ 35584],
| 99.95th=[ 5406720], 99.99th=[119013376]
bw ( KiB/s): min= 8192, max=1136744, per=99.01%, avg=104755.10, stdev=208227.89, samples=198
iops : min= 2048, max=284186, avg=26188.71, stdev=52057.00, samples=198
lat (usec) : 2=95.25%, 4=4.31%, 10=0.22%, 20=0.09%, 50=0.03%
lat (usec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2=0.03%, 4=0.01%, 10=0.01%, 20=0.01%, 50=0.01%
lat (msec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%
作业的IO统计信息:
IOPS=26.5k, BW=103MiB/s:IOPS、BW 性能指标值。
(10.0GiB/99102msec):总共读取的数据量(10G)以及消耗的时间(99102毫秒)。
接下来是 IO 延迟相关的信息:slat/clat/lat/clat percentiles。
slat (usec):提交延迟【微秒】,即“需要多久将IO提交到Kernel进行处理”,the time it took to submit the I/O to kernel for processing。
clat (usec):完成延迟,即IO提交到Kernel到IO完成返回之间的时间,the time that passes between submission to the kernel and when the IO is complete, not including submission latency。
lat (usec):lat is the best metric which represents the whole latency an application would expericen. The avg slat + avg clat =~ avg lat 。
clat percentiles:clat的分布统计数据,表示 clat “置信级”。
90.00th=[ 1768]:表明 90% 的 IO 的平均 clat 是1768 nsec。
NOTES:其计算方式,所有 IO 结束后,按照每个 IO clat 的值从小到大依次排序,并分别计算出前1%的平均clat,如:1.00th=[ 1160],百分比越大,clat的值也会随着增大。
bw/iops 的统计信息。
Bandwidth minimum, maximum, percentage of aggregate bandwidth received, average and standard deviation.
接下来就是:lat的统计分布数据,如下:
lat (usec) : 2=95.25%, 4=4.31%, 10=0.22%, 20=0.09%, 50=0.03%
lat (usec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2=0.03%, 4=0.01%, 10=0.01%, 20=0.01%, 50=0.01%
lat (msec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%
如:2=95.25%,表明 95.25% 的 IO requests 完成的时延小于2 usec (微秒),4=4.31%,4.31% 的request 完成的时延在 2 微秒和 4 微秒之间 [2, 4),即大于等于 2 微秒,小于 4 微秒。
part 5
cpu : usr=1.94%, sys=4.69%, ctx=2328, majf=0, minf=62
CPU相关统计信息:
ctx:运行过程中,上下文切换次数
majf/minf:major/minor page faults的数量
part 6
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 rwt: total=2621440,0,0, short=0,0,0, dropped=0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
IO 队列深度的统计分布情况:
IO depths:Distribution of I/O depths over the job lifetime. Each entry covers depths from that value, and up to those that are lower than the next entry… e.g., 16=covers depths from 16 to 31。
…16=100.0%...”,表明job was able to always have 16 IO unit in flight agaist the device。
IO submit/complete: distribution of submit/complete. Each entry denotes that amount and below, until the previous entry. e.g., 16=100% means that we submitted anywhere between 9 to 16 I/Os per submit call...
4=100%means that we submitted anywhere between 1 to 4 IOs per submit call.
IO issued:Number of read/write/trim requests issued, and number of short or drop read/write requests.
IO latency:Distribution of I/O completion latencies. The numbers follow the same pattern as IO depths.
part 7:
Run status group 0 (all jobs):
READ: bw=103MiB/s (108MB/s), 103MiB/s-103MiB/s (108MB/s-108MB/s), io=10.0GiB (10.7GB), run=99102-99102msec
group statistics:
io=10.0GiB (10.7GB):读取的数据总量。
bw=103MiB/s (108MB/s):Aggregate bandwidth of all jobs/threads in the group。
103MiB/s-103MiB/s:Minimum/Maximum average bandwidth a thread saw.
run=99102-99102msec:mint/maxt Shortest runtime of threads in the group.
NOTES:If we have more than one thread to run in a group, so we can see different values for mint/minimum and maxt/maximum,,, here they're same, because we just have one job.
Part 8:
Disk stats (read/write):
rbd0: ios=3741/0, merge=7487/0, ticks=428805/0, in_queue=428827, util=99.12%
磁盘信息:
ios=3741/0, 作业运行过程中读写的 IO 数量,3741 read IO and 0 write IO on /dev/rbd0
merge: Number of merges IO fromthe I/O scheduler,即在 IO request queue 中被IO电梯算法合并的IO数量。
ticks: Number of ticks we kept the disk busy. A sign that the device is saturated.
in_queue:Total time spent in the disk queue.(毫秒),指 在 IO request queue 中消耗的时间。
util: 磁盘的利用率。
五、总结
通过本章的学习,我们了解了 fio 安装,fio 基本使用方式,以及 fio 输出结果中各字段所代表的含义。在接下来的一系列文章,我们将探索 fio 更多特性,期望通过该系列文章,能够熟练掌握 fio 测试工具,最终更好地为我们的测试工作服务。