5fc7b55215a5f2631.png_fo742.png

fio(Flexible IO Tester)是Jens Axboe编写的可用于基准测试和硬件压力测试的I/O工具
可以通过多线程或进程模拟各种io操作
可以模拟不同IO场景下的IO负载,它支持19种I/O引擎(sync, mmap, libaio, posixaio, SG v3, splice, null, network, syslet, guasi, solarisaio等),支持块设备和文件。
fio不需要使用root来支行,除非使用到的文件或是设备需要root权限。一些选项可能会被限制,比如内存锁,io调度器切换,或是nice value降级。
https://github.com/axboe/fio
http://freshmeat.sourceforge.net/projects/fio

yum install fio -y
#在fio官网下载源码文件,解压后./configure、make、make install之后就可以使用fio了

[root@wow ~]# fio --help
fio-2.2.8
fio [options] [job options]
--debug=options Enable debug logging. May be one/more of:
process,file,io,mem,blktrace,verify,random,parse,
diskutil,job,mutex,profile,time,net,rate,compress
--parse-only Parse options only, don't start any IO
--output Write output to file
--runtime Runtime in seconds
--bandwidth-log Generate per-job bandwidth logs
--minimal Minimal (terse) output
--output-format=x Output format (terse,json,normal)
--terse-version=x Set terse version output format to 'x'
--version Print version info and exit
--help Print this page
--cpuclock-test Perform test/validation of CPU clock
--crctest Test speed of checksum functions
--cmdhelp=cmd Print command help, "all" for all of them
--enghelp=engine Print ioengine help, or list available ioengines
--enghelp=engine,cmd Print help for an ioengine cmd
--showcmd Turn a job file into command line options
--eta=when When ETA estimate should be printed
May be "always", "never" or "auto"
--eta-newline=time Force a new line for every 'time' period passed
--status-interval=t Force full status dump every 't' period passed
--readonly Turn on safety read-only checks, preventing writes
--section=name Only run specified section in job file
--alloc-size=kb Set smalloc pool to this size in kb (def 1024)
--warnings-fatal Fio parser warnings are fatal
--max-jobs=nr Maximum number of threads/processes to support
--server=args Start a backend fio server
--daemonize=pidfile Background fio server, write pid to file
--client=hostname Talk to remote backend fio server at hostname
--remote-config=file Tell fio server to load this local job file
--idle-prof=option Report cpu idleness on a system or percpu basis
(option=system,percpu) or run unit work
calibration only (option=calibrate)
--trigger-file=file Execute trigger cmd when file exists
--trigger-timeout=t Execute trigger af this time
--trigger=cmd Set this command as local trigger
--trigger-remote=cmd Set this command as remote trigger

Fio was written by Jens Axboe jens.axboe@oracle.com
Jens Axboe jaxboe@fusionio.com
Jens Axboe axboe@fb.com

#常用参数说明:
ioengine=libaio //指定io引擎
userspace_reap //配合libaio,提高异步io的收割速度
rw=randrw //混合随机对写io,默认读写比例5:5
rwmixwrite=20 //在混合读写的模式下,写占20%
time_based //在runtime压力测试周期内,如果规定数据量测试完,要重复测试
runtime=180 //在180秒,压力测试将终止
direct=1 //设置非缓冲io,绕过机器自带的buffer。使测试结果更真实
group_reporting //如果设置了多任务参数numjobs,用每组报告代替每job报告
randrepeat=0 //设置产生的随机数是不可重复的
norandommap
nrfiles=8 每个进程生成文件的数量。
ramp_time=6
lockmem=1g 只使用1g内存进行测试
iodepth=16 #每一个文件的队列长度为16
iodepth_batch=8
iodepth_low=8
iodepth_batch_complete=8
exitall //一个job完成,就停止所有的
filename=/dev/mapper/cachedev #压力测试的文件名,支持文件系统或者裸设备,-filename=/dev/sda2或-filename=/dev/sdb
numjobs=1 //job的默认数量,也就是并发数,默认是1
bs=16k 单次io的块文件大小为16k
bsrange=512-2048 //数据块的大小范围,从512bytes到2048 bytes
size=200G //每个线程操作200G文件,以每次4k的io进行测试。
refill_buffers //每次提交后都重复填充io buffer
overwrite=1 //设置文件可覆盖
sync=1 //设置异步io
fsync=1 //一个io就同步数据
invalidate=1 //开始io之前就失效buffer-cache
directory=/your_dir // fielname参数值的前缀
thinktime=600 //在发布io前等待600秒
thinktime_spin=200 //消费cpu的时间,thinktime的剩余时间sleep
thinktime_blocks=2 //在thinktime之前发布的block数量
bssplit=4k/30:8k/40:16k/30 //随机读4k文件占30%、8k占40%、16k占30%
rwmixread=70 //读占70%

#用例:
顺序读 -rw=read
顺序写 -rw=write
随机写 -rw=randwrite
随机读 -rw=randread
混合随机读写(读占60%) -rw=randrw -rwmixread=60
混合随机读写(写占60%) -rw=randrw -rwmixwrite=60
fio -filename=/dev/vda1 -direct=1 -thread -rw=randread -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=60 -group_reporting -name=randread #随机读
fio -filename=/dev/vda1 -direct=1 -thread -rw=read -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=60 -group_reporting -name=read_seq #顺序读
fio -filename=/dev/vda1 -direct=1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=60 -group_reporting -name=randwrite #随机写
fio -filename=/dev/vda1 -direct=1 -thread -rw=write -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=60 -group_reporting -name=write_seq #顺序写
fio -filename=/dev/vda1 -direct=1 -thread -rw=randrw -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=60 -group_reporting -name=randrw -rwmixread=70 #随机读写

结果:
fio: terminating on signal 2
randread: (groupid=0, jobs=10): err= 0: pid=4164: Sat Feb 10 10:57:03 2018
read : io=1429.6MB, bw=19791KB/s, iops=1236, runt= 73965msec
#fio做了1429.6MB的IO,速率19791KB/s,总IOPS 1236 (16k block size),运行了73965ms。
clat (usec): min=64, max=135967, avg=8075.19, stdev=26213.23
#completion latency。这是命令提交到kernel到IO做完之间的时间,不包括submission latency。在老版本的fio中,这是估计应用级延迟的最好指标。
lat (usec): min=64, max=135967, avg=8075.51, stdev=26213.23
#这个值是从IO结构体创建时刻开始,直到紧接着clat完成,这个算法最好地表现出了应用程序的行为。
#submission latency。这个值和他的名字很相像,代表“盘需要多久将IO提交到kernel做处理?”。
clat percentiles (usec):
| 1.00th=[ 97], 5.00th=[ 131], 10.00th=[ 173], 20.00th=[ 205],
| 30.00th=[ 227], 40.00th=[ 253], 50.00th=[ 270], 60.00th=[ 294],
| 70.00th=[ 338], 80.00th=[ 398], 90.00th=[ 628], 95.00th=[96768],
| 99.00th=[96768], 99.50th=[96768], 99.90th=[97792], 99.95th=[97792],
| 99.99th=[99840]
#这个列表可以在config文件中配置。在精简输出模式下有20个这样的格式,%f=%d; %f=%d;
bw (KB /s): min= 1376, max= 2432, per=10.02%, avg=1983.65, stdev=131.42
lat (usec) : 100=1.25%, 250=37.63%, 500=48.13%, 750=3.92%, 1000=0.58%
lat (msec) : 2=0.15%, 4=0.10%, 10=0.09%, 20=0.05%, 50=0.03%
lat (msec) : 100=8.07%, 250=0.01%
cpu : usr=0.03%, sys=0.18%, ctx=91541, majf=0, minf=48
#用户/系统CPU占用率,进程上下文切换(context switch)次数,主要和次要(major and minor)页面错误数量(page faults)。
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
#Fio有一个iodepth设置,用来控制同一时刻发送给OS多少个IO。这完全是纯应用层面的行为,和盘的IO queue不是一回事。
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%
#submit和complete代表同一时间段内fio发送上去和已完成的IO数量。
#对于产生这个输出的垃圾回收测试用例来说,iodepth是默认值1,所以100%的IO在同一时刻发送1次,放在1-4栏位里。
#通常来说,只有iodepth大于1才需要关注这一部分数据。
issued : total=r=91488/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
#发送的IO数量
latency : target=0, window=0, percentile=100.00%, depth=1
#四个值分别代表预设的latency_target, latency_window, latency_percentile和iodepth。

Run status group 0 (all jobs):
READ: io=1429.6MB, aggrb=19790KB/s, minb=19790KB/s, maxb=19790KB/s, mint=73965msec, maxt=73965msec
#Fio支持把不同的测试聚合。例如,我可以用一个配置文件混合包含SSD和HDD,但是设置分组(group)把IO单独汇总。
Disk stats (read/write):
vda: ios=91512/137, merge=0/30, ticks=740573/224, in_queue=740819, util=99.83%

io= 总共执行了多少size的IO
bw= 平均IO带宽
iops= IOPS
runt= 线程运行时间
slat 提交延迟
clat 完成延迟
lat响应时间
bw 带宽
cpu利用率
IO depths=io队列
IO submit=单个IO提交要提交的IO数
IO complete= Like the above submit number, but for completions instead.
IO issued= The number of read/write requests issued, and how many
of them were short.
IO latencies=IO延迟的分布
aggrb= group总带宽
minb= 最小平均带宽.
maxb= 最大平均带宽.
mint= group中线程的最短运行时间.
maxt= group中线程的最长运行时间.
ios= 所有group总共执行的IO数.
merge= 总共发生的IO合并数.
ticks= Number of ticks we kept the disk busy.
in_queue= 花费在队列上的总共时间.
util= 磁盘利用率

1 对 “fio磁盘压力测试”的想法;

  1. 应用程序使用IO通常有二种方式:同步和异步。 同步的IO一次只能发出一个IO请求,等待内核完成才返回,这样对于单个线程iodepth总是小于1,但是可以通过多个线程并发执行来解决,通常我们会用16-32个线程同时工作把iodepth塞满。 异步的话就是用类似libaio这样的linux native aio一次提交一批,然后等待一批的完成,减少交互的次数,会更有效率。

    io队列深度通常对不同的设备很敏感,那么如何用fio来探测出合理的值呢?在fio的帮助文档里是如何解释iodepth相关参数的

    iodepth=int
    iodepth_batch=int
    iodepth_batch_complete=int
    iodepth_low=int
    fsync=int
    direct=bool

    这几个参数在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在电梯口排队着。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code