FIO是测试磁盘IOPS的非常好的工具,用来对硬件进行压力测试和验证,支持13种不同的I/O引擎,包括:sync,mmap,libaio,posixaio,SG v3,splice,null,network,syslet,guasi,solarisaio等等。
安装使用
直接yum安装
1 |
$ yum install libaio-devel fio |
语法:
1 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 32 -thread -rw=randread -ioengine=libaio -bs=4k -size=2G -numjobs=10 -runtime=1000 -group_reporting -name=mytest |
参数说明:
filename=/dev/sdb:测试文件名称,通常选择需要测试的盘的data目录。
direct=1:测试过程绕过机器自带的buffer,使测试结果更真实。
rw=randwrite:测试随机写的I/O。
rw=randrw:测试随机写和读的I/O。
bs=16k:单次io的块文件大小为16k。
bsrange=512-2048:同上,提定数据块的大小范围。
size=2g:本次的测试文件大小为2g,以每次4k的io进行测试。
numjobs=10:创建特定数目的job副本,可能是创建大量的线程/进程来执行同一件事,我们将这一系列的job看作一个特定的group。
runtime=1000:测试时间为1000秒,如果不写则一直将5g文件分4k每次写完为止。
ioengine=libaio:定义job向文件发起的io方式,一般有:sync表示基本的read、write、lseek操作;psync表示基本的pread、pwrite;libaio是linux专有的异步IO,Linux仅支持非buffer io的队列行为。
rwmixwrite=30:在混合读写的模式下,写占30%。
group_reporting:关于显示结果的,汇总每个进程的信息。
随着块设备的发展,特别是SSD盘的出现,设备的并行度越来越高。要想利用好这些设备,有个诀窍就是提高设备的iodepth, 一次喂给设备更多的IO请求,让设备有机会来安排合并以及内部并行处理,提高总体效率。
应用程序使用IO通常有二种方式:同步和异步,同步的IO一次只能发出一个IO请求,等待内核完成才返回,这样对于单个线程iodepth总是小于1,但是可以通过多个线程并发执行来解决,通常我们会用16-32个线程同时工作把iodepth塞满。 异步的话就是用类似libaio这样的Linux native aio一次提交一批,然后等待一批的完成,减少交互的次数,会更有效率。
如果IO引擎是异步,那么我们需要调整好IO队列深度,IO队列深度通常对不同的设备很敏感,那么如何用fio来探测出合理的值呢?
在fio的帮助文档里是如何解释iodepth相关参数的:
iodepth=int
异步IO下的IO队列数,默认值为1。
iodepth_batch=int
一次批量提交多少IO,默认值1。
iodepth_batch_complete=int
默认值1,这个选项定义了一次取回多少个IO,如果定义为1的话,意味着我们将向内核请求最小为1个IO。
iodepth_low=int
这个水位标志表明什么时候开始重新填充这个队列,默认是同iodepth是一样的,意味着,没时没刻都在尝试填满这个队列,如果iodepth设置为16,而iodepth设置为4的话,那么fio将等到depth下降到4才开始重新填充。默认根据iodepth值来定。
fsync=int
如果写一个文件的话,每N次IO传输完block后,都会进行一次同步脏数据的操作。
direct=bool
这几个参数在libaio的引擎下的请求流程:
libaio引擎会用iodepth值来调用io_setup准备一个可以一次提交iodepth个IO的上下文,同时申请一个io请求队列用于保持IO。 在压测进行的时候,系统会生成特定的IO请求,往io请求队列里面扔,当队列里面的IO数量达到iodepth_batch值的时候,就调用io_submit批次提交请求,然后开始调用io_getevents开始收割已经完成的IO。 每次收割多少呢?由于收割的时候,超时时间设置为0,所以有多少已完成就算多少,最多可以收割iodepth_batch_complete值个。随着收割,IO队列里面的IO数就少了,那么需要补充新的IO。什么时候补充呢?当IO数目降到iodepth_low值的时候,就重新填充,保证OS可以看到至少iodepth_low数目的io在电梯口排队着。
SAS盘测试(Raid5)
下面进行测试,部门信息省略,主要看读写速度和iops即可;另外,在测试的时候顺便加上了iostat给出的结果。
4k,随机读测试
1 2 3 4 5 6 7 8 9 10 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=randread -ioengine=libaio -bs=4k -size=512M -numjobs=1 -runtime=1000 -group_reporting -name=mytest Starting 1 thread Jobs: 1 (f=1): [r] [100.0% done] [98744K/0K/0K /s] [24.7K/0 /0 iops] [eta 00m:00s] mytest: (groupid=0, jobs=1): err= 0: pid=83808: Thu Mar 9 14:02:57 2017 ............................................................ Run status group 0 (all jobs): READ: io=524288KB, aggrb=88189KB/s, minb=88189KB/s, maxb=88189KB/s, mint=5945msec, maxt=5945msec Disk stats (read/write): sdb: ios=125241/0, merge=0/0, ticks=92700/0, in_queue=92775, util=97.48% |
1 2 3 |
$ iostat -dxk 1 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sdb 0.00 0.00 24055.00 0.00 96220.00 0.00 8.00 15.86 0.66 0.66 0.00 0.04 100.00 |
rrqm/s: 每秒对该设备的读请求被合并次数,文件系统会对读取同块(block)的请求进行合并。
wrqm/s:每秒对该设备的写请求被合并次数。
r/s:每秒读取的次数(IOPS)。
w/s:每秒写入的次数(IOPS)。
rsec/s:每秒读取的扇区数。
wsec/s:每秒写入的扇区数。
rKB/s:每秒读数据量(kB为单位)。
wKB/s︰ 每秒写数据量(kB为单位)。
avgrq-sz:平均每次IO操作的数据量(扇区数为单位)。
avgqu-sz:平均等待处理的IO请求队列长度。
await:每一个IO请求的处理的平均时间(单位是微秒毫秒)。这里可以理解为IO的响应时间,一般地系统IO响应时间应该低于5ms,如果大于10ms就比较大了。
svctm:平均每次IO请求的处理时间(毫秒为单位)。
%util:在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度。一般地,如果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘,即使%util是100%,因为磁盘的并发能力,所以磁盘使用未必就到了瓶颈)。
以上各值之间也存在联系,我们可以由一些值计算出其他数值,例如:
util = (r/s+w/s) * (svctm/1000)
对于上面的例子有:util = (7.8+31.49)*(2.62/1000) = 0.098
16k,随机读
1 2 3 4 5 6 7 8 9 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=randread -ioengine=libaio -bs=16k -size=2G -numjobs=1 -runtime=1000 -group_reporting -name=mytest Jobs: 1 (f=1): [r] [100.0% done] [126.5M/0K/0K /s] [8094 /0 /0 iops] [eta 00m:00s] mytest: (groupid=0, jobs=1): err= 0: pid=88464: Thu Mar 9 14:26:28 2017 ................................................................ Run status group 0 (all jobs): READ: io=2048.0MB, aggrb=99888KB/s, minb=99888KB/s, maxb=99888KB/s, mint=20995msec, maxt=20995msec Disk stats (read/write): sdb: ios=129726/0, merge=0/0, ticks=333343/0, in_queue=333417, util=99.47% |
1 2 3 |
$ iostat -dkx 1 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sdb 0.00 0.00 7029.00 0.00 112464.00 0.00 32.00 15.96 2.27 2.27 0.00 0.14 100.00 |
4k,顺序读
1 2 3 4 5 6 7 8 9 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=read -ioengine=libaio -bs=4k -size=2G -numjobs=1 -runtime=1000 -group_reporting -name=mytest Starting 1 thread Jobs: 1 (f=1): [R] [100.0% done] [400.2M/0K/0K /s] [102K/0 /0 iops] [eta 00m:00s] .................................................................. Run status group 0 (all jobs): READ: io=2048.0MB, aggrb=425558KB/s, minb=425558KB/s, maxb=425558KB/s, mint=4928msec, maxt=4928msec Disk stats (read/write): sdb: ios=521161/0, merge=0/0, ticks=66757/0, in_queue=66672, util=98.02% |
1 2 3 |
$ iostat -dxk 1 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sdb 0.00 0.00 102237.00 0.00 408952.00 0.00 8.00 13.77 0.13 0.13 0.00 0.01 100.00 |
16k,顺序读
1 2 3 4 5 6 7 8 9 10 11 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=read -ioengine=libaio -bs=16k -size=4G -numjobs=1 -runtime=1000 -group_reporting -name=mytest fio-2.0.13 Starting 1 thread Jobs: 1 (f=1): [R] [100.0% done] [671.3M/0K/0K /s] [42.1K/0 /0 iops] [eta 00m:00s] mytest: (groupid=0, jobs=1): err= 0: pid=88870: Thu Mar 9 14:28:45 2017 ................................................................. Run status group 0 (all jobs): READ: io=5120.0MB, aggrb=809711KB/s, minb=809711KB/s, maxb=809711KB/s, mint=6475msec, maxt=6475msec Disk stats (read/write): sdb: ios=324575/0, merge=0/0, ticks=99176/0, in_queue=99137, util=98.49% |
1 2 3 |
$ iostat -dkx 1 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sdb 0.00 0.00 42788.00 0.00 684608.00 0.00 32.00 15.67 0.37 0.37 0.00 0.02 100.00 |
4k,随机写
1 2 3 4 5 6 7 8 9 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=randwrite -ioengine=libaio -bs=4k -size=1G -numjobs=1 -runtime=1000 -group_reporting -name=mytest Starting 1 thread Jobs: 1 (f=1): [w] [-.-% done] [0K/354.1M/0K /s] [0 /90.9K/0 iops] [eta 00m:00s] ....................................................................... Run status group 0 (all jobs): WRITE: io=1024.0MB, aggrb=319104KB/s, minb=319104KB/s, maxb=319104KB/s, mint=3286msec, maxt=3286msec Disk stats (read/write): sdb: ios=0/243732, merge=0/0, ticks=0/45305, in_queue=45275, util=95.35% |
1 2 3 |
$ iostat -dkx 1 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sdb 0.00 0.00 0.00 90953.00 0.00 363820.00 8.00 14.54 0.16 0.00 0.16 0.01 100.00 |
16k,随机写
1 2 3 4 5 6 7 8 9 10 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=randwrite -ioengine=libaio -bs=16k -size=2G -numjobs=1 -runtime=1000 -group_reporting -name=mytest Starting 1 thread Jobs: 1 (f=1): [w] [100.0% done] [0K/130.5M/0K /s] [0 /8348 /0 iops] [eta 00m:00s] mytest: (groupid=0, jobs=1): err= 0: pid=89757: Thu Mar 9 14:33:20 2017 .............................................................. Run status group 0 (all jobs): WRITE: io=2048.0MB, aggrb=102771KB/s, minb=102771KB/s, maxb=102771KB/s, mint=20406msec, maxt=20406msec Disk stats (read/write): sdb: ios=0/130672, merge=0/0, ticks=0/323327, in_queue=323321, util=99.45% |
4k,顺序写
1 2 3 4 5 6 7 8 9 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=write -ioengine=libaio -bs=4k -size=2G -numjobs=1 -runtime=1000 -group_reporting -name=mytest Starting 1 thread Jobs: 1 (f=1): [W] [100.0% done] [0K/382.7M/0K /s] [0 /97.1K/0 iops] [eta 00m:00s] ................................................................. Run status group 0 (all jobs): WRITE: io=3072.0MB, aggrb=411582KB/s, minb=411582KB/s, maxb=411582KB/s, mint=7643msec, maxt=7643msec Disk stats (read/write): sdb: ios=0/762399, merge=0/0, ticks=0/105009, in_queue=104903, util=98.72% |
1 2 3 |
$ iostat -dkx 1 Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sdb 0.00 0.00 0.00 97888.00 0.00 391556.00 8.00 14.30 0.15 0.00 0.15 0.01 100.00 |
16k,随机写
1 2 3 4 5 6 7 8 9 10 11 |
$ fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=write -ioengine=libaio -bs=16k -size=5G -numjobs=1 -runtime=1000 -group_reporting -name=mytest mytest: (g=0): rw=write, bs=16K-16K/16K-16K/16K-16K, ioengine=libaio, iodepth=16 fio-2.0.13 Starting 1 thread Jobs: 1 (f=1): [W] [100.0% done] [0K/652.9M/0K /s] [0 /41.8K/0 iops] [eta 00m:00s] ............................................................. Run status group 0 (all jobs): WRITE: io=5120.0MB, aggrb=821253KB/s, minb=821253KB/s, maxb=821253KB/s, mint=6384msec, maxt=6384msec Disk stats (read/write): sdb: ios=0/317745, merge=0/0, ticks=0/91548, in_queue=91494, util=98.45% |
PS:测试中发现,随着线程数的增大,IO读写能力立马提高。另外这里我使用的都是libaio,你也可以使用psync测试,我测试的psync比libaio慢很多。还有测试Raid 1发现比Raid 5慢很多很多。
SSD盘测试
4k,随机读
4k,随机写
16k,顺序写
参考:http://blog.yufeng.info/archives/2104