一、简介
FIO为Linux kernel的IO部分维护者axobe开发,
Github:
https://github.com/axboe/fio。FIO的详细使用方法参见自带的HOWTO文件。
FIO一种IO系统的Benchmark和压力测试工具,可以模拟不同IO场景下的IO负载。最初axobe设计FIO是为了节省为特定负载设计专门测试程序、进行性能测试,以及debug的时间。
写测试程序非常浪费时间,因为不同的测试负载的IO场景不同,他们都用自己的方式产生IO,故需要模拟这些IO负载,FIO需足够灵活。
FIO
支持 13
种不同的 I/O 引擎, 包括:sync, mmap, libaio, posixaio, SG v3, splice, null, network,
syslet,guasi,solarisaio 等等。 FIO 的引擎能识别简单易懂的job file文本去进行测试
,同时能提供各种 I/O 性能指标,如I/O 延迟、IOPS和带宽等。因此
被大量的制造商和广泛的用户认可,作为确认IO系统良好的测试工具。
二、典型工作过程
FIO命令行格式:fio [options] [job options] <job file(s)>
1. 运行过程
1)确定待模拟IO负载的IO参数,如I/O type,Block size,I/O engine,I/O depth,Target file/device等。可以配合fio的一些命令行参数来涉及I/O参数。如--parse-only或--showcmd等。
2)写一个 job file来描述要simulate的 I/O 负载。一个 job 文件可以控制产生任意数目
的线程和文件。典型的 job 文件有一个 global 段(定义共享参数),一个或多个
job 段(描述具体要产生的 job)。
3)运行时,FIO 从文件读这些参数,做处理,并根据这些参数描述,启动这些simulate线
程/进程。
4)测试完成后,输出测试结果。
5)对FIO测试结果进行分析,评估IO系统的设计或优化方案或确定debug思路。
2. 运行方式
按参数输入方式分为如下两种:
1) 命令行方式:如
FIO –filename=/dev/sdb –direct=1 –rw=randread –bs=4k –size=60G –
numjobs=64 –runtime=10 –group_reporting –name=test
2) fio job_file 方式:如
job_file 的名字为 test,则运行方式为 fio test。
按FIO工作模式分为如下两种:
1)client/server方式:FIO工作模式可以分为前端和后端,即client端和server端。server端执行fio --server,client端执行fio --client=hostname jobfile,这样client端就可以把jobfile发到server端来执行,hostname为server端的IP。
2)本地执行:命令行/job file。
3. 命令行选项
FIO有很多有用的命令行选项,具体请直接查看fio --help或HOWTO文档。这里简单列出如下几个:
- --parse-only:仅解析configuration文件的参数使用是否正确;
- --output:结果输入到一个文件中;
- --cmdhelp=cmd:打印某个命令的帮助文档;
- --showcmd:解析配置文件并转化成命令行参数;
三、常用参数
1) IO type:表示 I/O 类型,Read Write;包括:Read 顺序读、 Write 顺序写、
RandWrite 随机写、 RandRead 随机读。
例如:rw=randwrite。
2) Block Size: 测试工具向被测设备发出的读写数据块的大小,可以是一个单独的
值,也可以是一个范围。
例如:blocksize=4k,
4K 是主流,8K 是 Mysql和 Oracle,16K 是 MysqlInnodb。
3) IO engine: I/O 引擎,处理 IO 的方式,定义了发起 IO 的方式,可以是内存映
射文件,可以是使用普通的读/写,我们可以使用 splice,异步 IO,syslet,甚至 SG
(SCSI generic sg) 。包括 sync,pync,vsync,libaio 等,目前使用最广泛的
是 libaio。
- Sync:基本的read,write。通过lseek来作定位;
- Psync:基本的pread,pwrite,在文件描述符给定的位置偏移上读取或写入数据,pread() 从文件 fd 指定的偏移 offset (相对文件开头) 上读取 count 个字节到buf 开始位置。文件当前位置偏移保持不变。 pwrite() 把缓存区 buf 开头的 count个字节写入文件描述符 fd offset 偏移位置上,文件偏移没有改变。 fd 引用的文件必须是可定位的,属于同步I/O;
- Vsync:基本的 readv, writev;
- Libaio: Linux 专有的异步 IO,Linux 仅支持非 buffered IO 的队列行为;
- 同步和异步的区别:同步 IO 是指,进程触发 IO 操作后,后面的操作不能进行,只能等待 IO 操作完成或者放弃 IO 操作,保证当前只有一个 IO 操作在进行。异步 IO 是指,触发 IO 操作以后,直接返回,可以继续执行后面的操作,IO 交给内核来处理,完成后内核通知进程 IO 完成。
- libaio 引擎会用这个 iodepth 值来调用 io_setup,准备可以一次提交iodepth 个 IO 的上下文,同时申请iodepth个 io 请求队列用于保持 IO。在压测进行的时候,系统会生成特定的 IO 请求,往 io 请求队列里面提交,当队列里面的IO个数达到 iodepth_batch值的时候,就调用 io_submit 批次提交请求,然后开始调用 io_getevents 开始收割已经完成的 IO。每次收割多少呢?由于收割的时候,超时时间设置为 0,所以有多少已完成的 IO 就收割多少,最多可以收割 iodepth_batch_complete 个 IO。随着收割,IO 队列里面的 IO 数就少了,那么需要补充新的 IO。什么时候补充呢?当 IO 数目降到 iodepth_low 值的时候,就重新填充,保证 OS 可以看到至少 iodepth_low 数目的 io 在电梯口排队着。
- libaio,这个是追求 IOPS 的;对于延时为主的测试,建议使用 psync。
4) IO size: 总共要读写的数据大小。
例如:size=200G
5) IO depth:测试的队列深度,队列深度表示控制器可同时发送给被测设备的指令数
目。在 ATA 指令集的 Read/Write FP DMA Queue 指令中,可以给每个读写指令
带上标签。当队列深度为1时,控制器需要等待被测设备完成指令并返回结果后才
可执行下一条指令;当队列深度大于 1 时,控制器可以向被测设备发出多条指令,
并给每个指令附带一个标签作为指令号,此时被测设备并不按照指令号的顺序返回
结果,从而可根据自身 Firmware 算法进行优化,寻找最容易得到的结果并反馈给
控制器。当某一条指令的结果返回之后,该标签被回收并可再次利用。针对 SATA
硬盘或 SSD,需要控制器工作在 AHCI 模式并且操作系统加载 AHCI 驱动程序且被
测设备本身要支持 NCQ 才能支持此种访问模式。按照上述原理,在队列深度增加
时,被测设备的访问效率将有明显提升,故性能也有相应提升。 默认对于每个文件
来说是 1,可以设置一个更大的值来提高并发度。
例如:iodepth=1
6) IO type:表示我们将执行 buffered io 还是 direct/raw io。 ZFS 和 Solaris 不支持
direct io,在 windows 上同步 IO 引擎不支持 direct io。 Direct=0 时,则表明采
用 buffered io。
例如:direct=1
7) Num files: 表示负载将分发到几个文件中。
例如:nrfiles=8
8) Num threads: 创建多少个进程/线程来并发执行。
例如:numjobs=1。
numjobs 建议等于 CPU 的 core 值,即 HT=off。
9) Runtime: 测试运行时间。
例如:runtime=30
10)数据填充方式: 当进行数据写入时,可选择写入数据的形式。此选项可选三种模式,
分别为重复填充、伪随机填充、随机填充。重复填充表示全 0 的数据写入,当 SSD
主控支持数据压缩功能时,大量的全 0 数据将以压缩的方式写入 SSD 从而显著提
高性能;伪随机填充写入即为伪随机数的填充写入,由于生成随机数需要花费大量
时间,故在通常测试中,为减少等待时间,一般选择伪随机数填充。在选择伪随机
数写入后,SSD 主控即使支持数据压缩功能也不能够对伪随机数进行压缩;全随机
填充即为先进行随机数生成,之后再进行写入。随机数生成会消耗大量时间,通常
测试中不采用此种模式。
例如:refill_buffers
11) percentage_random:随机和顺序比率;
例如:percentage_random=80,80%的随机。
12) time_based :决定脚本的运行时间,即使 file 已被完全读写或写完,也要执行完
runtime 规定的时间。它是通过循环执行相同的负载来实现的。
例如:time_based。
13) 目标盘符/被测盘符:当需要测试多个磁盘时,需要增加多行以下内容,
例如: filename=/dev/sdb; 如果写在配置文件中,则需创建多个job区分多个不同的测试目标设备;
四、结果分析
1. slat:submission latency提交延迟,意思为“how long did it take to submit this IO to the kernel for processing?”;
2. clat:completion latency完成延迟,意思为“This is the time that passes between submission to the kernel and when the IO is complete, not including submission latency”;
3. clat percentiles:描述IO整体延迟latency distribution,为不同百分比IO的clat。可以根据这些百分比数来绘制图形,从整体上分析IO系统的IO延时。这是非常有用的一个用来描述IO系统延时情况的指标,例如可以比较TP99、TP90等性能指标。
4. IO depths:这个iodepth设置是用来控制在任意给定时刻,有多少个IO被提交给OS。这个参数完全是应用端来设置,与IO设备的IO queue不同。summit和complete表明fio一次提交多少个IO,或一次完成多少个IO。
Reference
1. FIO_HOWTO,见附件;
附件列表