Hamge

学习记录

导航

fio

文章转自:

https://static.mtyun.com/library/fio-introduction

 

fio是Jens Axboe大神编写的性能测试工具,可以用来测试CPU、网络以及存储等多种设备的性能数据,目前开源在github上(https://github.com/axboe/fio)。 fio的来由是axboe大神在日常性能测试工作中,发现很多重复、繁琐的工作,于是程序员的“惰性”大发,开发了fio这一测试工具——也可称之为框架,因为你可以编写自己的插件。

详细见:https://linux.die.net/man/1/fio

源码地址:https://github.com/axboe/fio/releases

fio安装

apt update
apt-get install libaio-dev -y
wget https://git.kernel.dk/cgit/fio/snapshot/fio-3.27.tar.gz
tar -zxvf fio-3.27.tar.gz
cd fio-3.27
./configure
make && mak install

 

fio架构简介

fio主要分为job管理、ioengine和数据收集等模块,其中ioengine是fio的核心。 fio ioengine采用类似于vfs的架构,即定义一组公共的操作方法(ioengineops),具体的ioengine可以通过实现ioengineops等指定接口,插入到fio框架中,并得以成功执行。 这一框架可通过下图得以简示:

 

 

下面以fio 2.1.1版本和以下配置文件(example.conf)为例,来看fio的主要流程:

[global]
group_reporting=1
iodepth=4
bsrange=4k-16k
ioengine=libaio
nrfiles=20
size=250G
filesize=1m-256m
numjobs=32
runtime=1000
create_serialize=1

[random-read]
name=random-read
rw=randread
directory=/tmp/fiotest

 

基于这一配置文件,fio example.conf的大执行流程为:

  1. 解析配置文件。
  2. 准备测试文件,创建nrfiles个文件,命名为“$jobname.$[1~numjobs].$[1~nrfiles]”,总共会创建nrfiles*numjobs个文件。如果create_serialize=0,文件的创建会在各个进程中进行,于是文件创建动作相互交织,文件的分布更为随机。
  3. 创建numjobs个进程或者线程(thread=0/1参数可控),执行fio任务。
  4. 在每个fio任务中,tdioinit()会钓鱼ioengine的init()函数,进行ioengine的初始化,随后执行其他一些初始化工作,比如设置计时器等。
  5. 每个fio任务中,代码执行到do_io(),开始执行真正的IO工作。

部分参数

filename=/dev/vdb     支持文件系统或者裸设备,-filename=/dev/sdb或-filename=/data/fiotest
direct=1                 测试过程绕过机器自带的buffer,使测试结果更真实
rw=randwread             测试随机读的I/O
rw=randwrite             测试随机写的I/O
rw=randrw                测试随机混合写和读的I/O
rw=read                  测试顺序读的I/O
rw=write                 测试顺序写的I/O
rw=rw                    测试顺序混合写和读的I/O
bs=4k                    单次io的块文件大小为4k
bsrange=512-2048         同上,提定数据块的大小范围
size=5g                  本次的测试文件大小为5g,以每次4k的io进行测试
numjobs=30               本次的测试线程为30
runtime=1000             测试时间为1000秒,如果不写则一直将5g文件分4k每次写完为止
ioengine=psync           io引擎使用pync方式,如果要使用libaio引擎,需要yum install libaio-devel包
rwmixwrite=30            在混合读写的模式下,写占30%
group_reporting          关于显示结果的,汇总每个进程的信息
此外
lockmem=1g               只使用1g内存进行测试
zero_buffers             用0初始化系统buffer
nrfiles=8                每个进程生成文件的数量

 

fio输出解析

以loop块设备的fio输出结果为例,图示各个部分的含义:

 结果参数

io=执行了多少M的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完延迟的分布

io=总共执行了多少size的IO
aggrb=group总带宽
minb=最小.平均带宽.
maxb=最大平均带宽.
mint=group中线程的最短运行时间.
maxt=group中线程的最长运行时间.

ios=所有group总共执行的IO数.
merge=总共发生的IO合并数.
ticks=Number of ticks we kept the disk busy.
io\_queue=花费在队列上的总共时间.
util=磁盘利用率

 

 

fio如何测量IOPS

使用fio测量存储设备或系统的IOPS值,使fio的常用使用场景之一。 那么fio使如何测量IOPS的?

在job开始之前的initiou()中,fio初始化三个队列,分别是iourequeues、ioufreelist和iouall。前者大小被初始化为iodepth最近的2^x,后二者大小被初始化为iodepth。 iourequeues实际上被实现为环,初始状态为head=tail=0。 ioufreelist和iouall都是FIFO,初始状态为nr=0;然后在initiou()的后面部分,fio通过iouqpush()往二者中放入相同的iodepth个新建的iou,flags均为IOUFFREE,并且会调用ioengine的iouinit()。 并且对于ioufreelist,在iou完成等情况发生时,fio通过putiou()回收iou,可被用来重复使用。

在doio时,会实现getiou,先检查如果iourequeues非空,则从其中取;如果ioufreelist非空,则从其中取。当然开始时一定是从后者成功取出iou。 tdioqueue(td, iou),调用ioengine的排队函数,以libaio ioengine为例,libaio的排队函数会将iou放入事先初始化的iocbs[]和ious[]数组,数组的大小也是iodepth。 当然如果libaio的队列已满,libaio的排队函数返回FIOQBUSY;如果iou操作是sync类型或trim,则返回FIOQCOMPLETED;否则排入队列并返回FIOQQUEUED。 实际上IOPS的计数是由td->ts.totaliou变量表示的。在返回FIOQCOMPLETED、FIOQQUEUED时,totaliou++。这就是fio的IOPS是如何被记录的

 

个人使用 

主要测试IOPS、吞吐、时延三个数据,Q表示IO深度,T表示线程数

IOPS 性能 > 
随机读 4K Q128T4 100G >
fio -direct=1 -iodepth=128 -thread -rw=randread -ioengine=libaio -bs=4k -size=100G -numjobs=4 -runtime=1000 -group_reporting -directory=/home/smb -name=Test

随机写 4K Q128T4 100G >
fio -direct=1 -iodepth=128 -thread -rw=randwrite -ioengine=libaio -bs=4k -size=100G -numjobs=4 -runtime=1000 -group_reporting -directory=/home/smb -name=Test 

吞吐性能 >
顺序读 1M Q32T4 100G >
fio -direct=1 -iodepth=32 -thread -rw=read -ioengine=libaio -bs=1m -size=100G -numjobs=4 -runtime=1000 -group_reporting -directory=/home/smb -name=Test   

顺序写 1M Q32T4 100G >
fio -direct=1 -iodepth=32 -thread -rw=write -ioengine=libaio -bs=1m -size=100G -numjobs=4 -runtime=1000 -group_reporting -directory=/home/smb -name=Test

时延性能 >
随机读 4K Q1T1 100G >
fio -direct=1 -iodepth=1 -thread -rw=randread -ioengine=libaio -bs=4k -size=100G -numjobs=1 -runtime=1000 -group_reporting -directory=/home/smb -name=Test          

随机写 4K Q1T1 100G >
fio -direct=1 -iodepth=1 -thread -rw=randwrite -ioengine=libaio -bs=4k -size=100G -numjobs=1 -runtime=1000 -group_reporting -directory=/home/smb -name=Test   

混合读写性能 >
R2:W8 256K Q32T4 100G >
fio -direct=1 -iodepth=32 -thread -rw=rw -ioengine=libaio -rwmixread=20 -bs=256k -size=100G -numjobs=4 -runtime=1000 -group_reporting -directory=/home/smb -name=Test   

R8:W2 256K Q32T4 100G >
fio -direct=1 -iodepth=32 -thread -rw=rw -ioengine=libaio -rwmixread=80 -bs=256k -size=100G -numjobs=4 -runtime=1000 -group_reporting -directory=/home/smb -name=Test 

 注意事项

1、同时在测试其他的设备裸设备时,一定要提前确定好此裸设备上是否有重要的数据,一定要重要的设备提前做好备份。fio会直接覆盖该磁盘空间中文件,请避开直接使用系统所在设备

2、建议使用顺序I/O和较大的blocksize 来测试设备的通吐量和延迟

3、建议使用随机I/O和较小的blocksize来测试设备的IOPS和延迟

4、在配置numjobs和iodepth 测试底层存储性能时,建议要深入了解应用到底采用的是同步的io还是异步的io(是多进程并发i/o请求还是一次提交一批的i/o的请求)

posted on 2021-10-11 10:59  Hamge  阅读(779)  评论(0编辑  收藏  举报