随着块设备的发展,特别是 SSD 盘的出现,设备的并行度越来越高。要想充分利用这些设备需要提高设备的 iodepth , 一次投喂更多的 IO 请求,让电梯算法和设备有机会来安排合并以及内部并行处理,提高总体效率。
fio 是一个 I/O 工具用来对设备进行压力测试和性能验证。
fio 支持13种不同的I/O引擎,包括:sync, mmap, libaio, posixaio, SG v3, splice, null, network, syslet, guasi, solarisaio, I/O priorities (针对新的Linux内核), rate I/O, forked or threaded jobs等。
应用程序使用 IO 通常有二种方式:同步和异步。
同步的 IO 一次只能发出一个 IO 请求,等待内核完成才返回,这样对于单个线程 iodepth 总是小于1,但是可以通过多个线程并发执行来解决,通常我们会用 16-32 个线程同时工作把 iodepth 塞满。 异步的话就是用类似 libaio 这样的 linux native aio 一次提交一批,然后等待一批的完成,减少交互的次数,会更有效率。
测试类别
测试类别 | 说明 |
---|---|
randread | 随机读 |
randwrite | 随机写 |
read | 顺序读 |
write | 顺序写 |
randrw | 混合随机读写,结合 rwmixread 或 rwmixwrite 使用 |
rw | 混合顺序读写,结合 rwmixread 或 rwmixwrite 使用 |
安装
从源码编译安装:
- 安装 gcc、zlib-dev/zlib-devel、make,用以编译 fio。
yum install -y gcc zlib-dev* make;
- 安装 libaio 和 libaio-devel 包,如果没有安装这两个包,fio 不能使用异步的 libaio 作为引擎,
yum install -y libaio libaio-devel
- 下载 fio 源码,如:fio-2.20.tar.gz、fio-3.33.tar.gz,解压并进入 fio 源码目录:
./configure && make && make install
直接从源安装:
4. yum install -y fio
常用参数
更多可参考官网说明:https://fio.readthedocs.io/en/latest/fio_doc.html#job-file-parameters
类型 | 参数名称 | 解释 |
---|---|---|
IO引擎 | ioengine | 定义fio如何下发IO请求(或者说:定义IO引擎类型),fio支持的IO引擎如下所示:sync, libaio, psync, vsync, psyncv, posixaio, solarisaio, windowsaio, mmap, splice, syslet-rw, sg, null, net, netsplice, rdma, cpuio, guasi, falloc, e4defrag, external |
读写类型 | rw | 定义测试的读写类型,可选的值如下:read, write表示顺序读,顺序写;rw, readwrite表示混合顺序读写;randread, randwrite表示随机读,随机写;randrw表示混合随机读写;对于读写混合的类型来说,默认的读写比为1:1; |
IO类型 | direct | 定义是否使用Direct IO;值为0,表示使用buffered IO;值为1,表示使用direct IO; |
IO块大小 | bs | 定义IO的块大小(block size),单位是k, K, m, M等,默认IO块大小为4KB;如果参数值仅为1个数字,比如bs=4k,则读写IO都是4KB; |
数据量 | size | 设置IO操作的数据量,除非另外指定了runtime这类参数,fio会将指定大小的数据量全部读/写完成,然后才停止测试。该参数的值,可以是带单位的数字,比如size=2G,表示读/写的数据量为2GB;也可以是百分数,比如size=20%,表示读/写的数据量占该设备/文件的20%的空间; |
队列深度 | iodepth | 设置IO队列深度,默认值为1。只适用在异步IO (libaio) 场景,同步IO场景因为要等待前一个任务完成才下发下一个任务,所以iodepth并不起作用。注意:这里的队列深度是每个线程的队列深度,如果有多个线程测试,意味着每个线程都是这么大的队列深度。Fio总的IO并发数=iodepth * numjobs |
测试文件 | filename | 设置待测试文件,在Linux下,任何设备都是文件,所以这里的文件既可指代真实的文件,也可以指代待测设备。 |
进程数 | numjobs | 定义测试的并发数。注意:各个进程/线程的测试结果默认是分别报告的,如果不想查看各个进程/线程的报告,而想要查看所有进程/线程的统计结果,可以搭配使用参数group_reporting。 |
结果汇总 | group_reporting | 关于显示结果的,汇总每个进程的信息。 |
读操作比例 | rwmixread | 在混合读写的模式下,读操作所占比例。【两者设置其一即可】 |
写操作比例 | rwmixwrite | 在混合读写的模式下,写操作所占比例。【两者设置其一即可】 |
内存限制 | lockmem | 如lockmem=1g,只使用1g内存进行测试。 |
文件数量 | nrfiles | 每个进程生成文件的数量。 |
文件大小 | filesize | 生成文件的大小。 |
被打开的文件数量 | openfile | 默认为nrfiles的值,指定同时打开的文件数量。 |
测试运行时间 | runtime | 单位为秒(s),在不设置size类的参数下,fio会完整运行整个测试时长,然后给出结果报告。 |
准备时间 | ramp_time | 单位为秒(s),跟runtime配合使用,测试总时长为ramp_time+runtime,但结果报告只计算在runtime期间的IO性能数据。 |
强制测试直至运行时间结束 | time_based | 如果设置了该参数,则本次测试会一直运行到runtime结束为止。默认值为0,如果规定了io_size之类的限定总IO大小参数,则会在完成总IO后提前停止测试。 |
常用测试实例
单盘测试
fio --group_reporting --rw=randread --direct=1 --ioengine=libaio --numjobs=4 --bs=4k --iodepth=32 --ramp_time=30 --runtime=300 --time_based --norandommap --randrepeat=0 --log_avg_msec=1000 --write_bw_log=4k-randread --write_iops_log=4k-randread --name=test --filename=/dev/sda --cpus_allowed=0-3
多盘测试
fio --group_reporting --rw= randread --direct=1 --ioengine=libaio --numjobs=12 --bs=4k --iodepth=32 --ramp_time=30 --runtime=300 --time_based --norandommap --randrepeat=0 --log_avg_msec=1000 --write_bw_log=4k-randread --write_iops_log=4k-randread --name=test1 --filename=/dev/sda --cpus_allowed=0-3 --name=test2 --filename=/dev/sdb --cpus_allowed=4-7 --name=test3 --filename=/dev/sdc --cpus_allowed=8-11