一、关于FIO

1.1 简介

FIO是一个开源的I/O压力测试工具,主要是用来测试磁盘的IO性能,也可测试cpu,nic的IO性能。它可以支持13种不同的I/O引擎,包括:sync,mmap, libaio, posixaio, SG v3, splice, network, syslet, guasi, solarisaio, I/Opriorities (针对新的Linux内核), rate I/O, forked or threaded jobs等。

fio 官网地址:http://freshmeat.net/projects/fio/

fio文档:https://fio.readthedocs.io/en/latest/index.html

2.1 常用测试场景

FIO相关测试场景:

顺序读写 (吞吐量,常用单位为MB/s):文件在硬盘上存储位置是连续的。

适用场景:大文件拷贝(比如视频音乐)。速度即使很高,对数据库性能也没有参考价值。

4K随机读写 (IOPS,常用单位为次):在硬盘上随机位置读写数据,每次4KB。

适用场景:操作系统运行、软件运行、数据库。

二、FIO安装

有三种安装方式

2.1 apt安装(Ubuntu)

#更新apt源
apt update
#安装fio
apt-get install fio

2.2 使用yum安装(centos)

#更新yum源
yum install epel-release
#安装fio
yum install libaio-devel fio

2.3 手动安装

wget http://brick.kernel.dk/snaps/fio-2.2.10.tar.gz yum install libaio-devel tar -zxvf fio-2.2.10.tar.gz cd fio-2.2.10
make
make install

附上一个基本涵盖所有操作系统的FIO包下载地址的网址:https://pkgs.org/download/fio

2.4 验证是否安装成功

输入:fio -h,看是否安装成功

三、FIO使用

3.1 fio参数解释

可以使用fio -help查看每个参数,具体的参数左右可以在官网查看how to文档,如下为几个常见的参数描述

filename=/dev/emcpowerb  支持文件系统或者裸设备,--filename=/dev/sdc或者--filename=/mnt/ccg/test_data(挂载的目录下任意文件名)

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               同上,提定数据块的大小范围,这里是随机生成一个范围

time_based                           如果设置的话,即使file已被完全读写或写完,也要执行完runtime规定的时间。它是通过循环执行相同的负载来实现的,与runtime相对应。

ramp_time=time                   设定在记录任何性能信息之前要运行特定负载的时间。这个用来等性能稳定后,再记录日志

size=5g                                本次的测试文件大小为5g,以每次4k的io进行测试,即生成读写的文件大小。

fdatasync=int                       同fsync,但是采用fdatasync()来同步数据,但不同步元数据

sync=bool                            使用sync来进行buffered写。对于多数引擎,这意味着使用O_SYNC

numjobs=30                        本次的测试线程为30

iodepth=1                            队列深度。默认是1,可以通过设置大于1的数来提升并发度。

runtime=1000                     测试时间为1000秒,如果不写则一直将5g文件分4k每次写完为止

ioengine=psync                  io引擎使用pync方式,如果要使用libaio引擎,需要yum install libaio-devel包

randrepeat=true                 对于随机IO负载,配置生成器的种子,使得路径是可以预估的,使得每次重复执行生成的序列是一样的。

rwmixwrite=30                   在混合读写的模式下,写占30%,推荐读写配比为7:3

group_reporting=1             关于显示结果的,汇总每个进程的信息

此外

lockmem=1g                     只使用1g内存进行测试

zero_buffers                     用0初始化系统buffer

nrfiles=8                           每个进程生成文件的数量

3.2 fio测试场景及生成报告详解

1)测试变量:

  • bs大小:(4k,16k,64k,1m)
  • 读写模式:(read,write,rw,randread,randwrite,randrw)
  • 使用libaio异步引擎,iodepth队列长度为128。
  • 运行时间为60s

第一种:4K,顺序写

fio --randrepeat= --ioengine=libaio --direct= --name=ccg_fio --iodepth= --numjobs= --size=1g --bs=4k --group_reporting= --readwrite=write --time_based= --runtime= --sync= --fdatasync= --filename=/mnt/ccg/4k_write

第二种:16K,顺序读

fio --randrepeat= --ioengine=libaio --direct= --name=ccg_fio --iodepth= --numjobs= --size=1g --bs=16k --group_reporting= --readwrite=read --time_based= --runtime= --sync= --fdatasync= --filename=/mnt/ccg/16k_read

第三种:16K,混合读写,70%读,30%写

fio --randrepeat= --ioengine=libaio --direct= --name=ccg_fio --iodepth= --numjobs= --size=1g --bs=16k --group_reporting= --readwrite=rw  -rwmixread= --time_based= --runtime= --sync= --fdatasync= --filename=/mnt/ccg/16k_rw

第四种:64k,随机写

fio --randrepeat= --ioengine=libaio --direct= --name=ccg_fio --iodepth= --numjobs= --size=1g --bs=64k --group_reporting= --readwrite=randwrite  --time_based= --runtime= --sync= --fdatasync= --filename=/mnt/ccg/64k_randwrite

第五种:1m,随机读

fio --randrepeat= --ioengine=libaio --direct= --name=ccg_fio --iodepth= --numjobs= --size=1g --bs=1m --group_reporting= --readwrite=randread  --time_based= --runtime= --sync= --fdatasync= --filename=/mnt/ccg/1m_randread

第六种:1m,随机读写,70%读,30%写

fio --randrepeat= --ioengine=libaio --direct= --name=ccg_fio --iodepth= --numjobs= --size=1g --bs=1m --group_reporting= --readwrite=randrw  -rwmixread=  --time_based= --runtime= --sync= --fdatasync= --filename=/mnt/ccg/1m_randrw

2)执行测试

root@client:/mnt/ccg# fio --randrepeat= --ioengine=libaio --direct= --name=ccg_fio --iodepth= --numjobs= --size=1g --bs=4k --group_reporting= --readwrite=write --time_based= --runtime= --sync= --fdatasync= --filename=/mnt/ccg/4k_write

报告详解

#这一行列出了执行的关键参数

ccg_fio: (g=0): rw=write, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=128

...

fio-2.2.10

Starting 16 processes

ccg_fio: Laying out IO file(s) (1 file(s) / 1024MB)

Jobs: 16 (f=16): [W(16)] [100.0% done] [0KB/98.11MB/0KB /s] [0/25.2K/0 iops] [eta 00m:00s]

ccg_fio: (groupid=0, jobs=16): err= 0: pid=77217: Mon Jul 27 17:42:01 2020

write: io=5662.2MB, bw=96631KB/s, iops=24157, runt= 60002msec              #io指的是读写的数据总量,iops是关键的测试指标,每秒io次数,runt是执行总时间

slat (usec): min=3, max=5087, avg=611.46, stdev=640.30                            #slat=提交延迟,代表IO提交到kernel做处理的过程

clat (usec): min=317, max=238746, avg=82794.77, stdev=24469.97            #clat=完成延迟,代表提交到kernel到IO做完之间的时间

lat (usec): min=500, max=238761, avg=83406.74, stdev=24540.97             #lat=响应时间,IO结构体创建时刻开始,直到紧接着clat完成

clat percentiles (msec):                                                                                   #分位分布图

|  1.00th=[   21],  5.00th=[   42], 10.00th=[   52], 20.00th=[   64],

| 30.00th=[   73], 40.00th=[   79], 50.00th=[   85], 60.00th=[   90],                 #50分位:85us

| 70.00th=[   95], 80.00th=[  101], 90.00th=[  110], 95.00th=[  120],              #90分位:110us,95分位:120us

| 99.00th=[  151], 99.50th=[  167], 99.90th=[  192], 99.95th=[  200],             #99分位:151us

| 99.99th=[  215]

bw (KB  /s): min=    4, max=14296, per=6.30%, avg=6087.37, stdev=1207.17                #bandwidth,带宽

lat (usec) : 500=0.01%, 750=0.01%, 1000=0.01%                                                            #latency分布:<500us占0.01%, 500us~750us占0.01%, <1000us占0.01

lat (msec) : 2=0.01%, 4=0.03%, 10=0.19%, 20=0.71%, 50=8.30%                                  #latency分布:<2ms占0.01%, 2ms~4ms占0.03%, 4ms~10ms占0.19%, 10ms~20ms占0.71%,20ms~50ms占8.3%

lat (msec) : 100=69.79%, 250=20.97%                                                                             #latency分布:<100ms占69.79%,100ms~250ms占20.97%

cpu          : usr=0.76%, sys=5.97%, ctx=2862343, majf=0, minf=5759                               #cpu=利用率,和top命令中类似

IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%        #IO depths=io队列

submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%      #IO submit=单个IO提交要提交的IO数

complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%       #IO complete=Like the above submit number, but for completions instead.

issued    : total=r=0/w=1449515/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0                  #IO issued=The number of read/write requests issued, and how many of them were short.

latency   : target=0, window=0, percentile=100.00%, depth=128                                     #IO latencies=IO完延迟的分布

Run status group 0 (all jobs):

WRITE: io=5662.2MB, aggrb=96631KB/s, minb=96631KB/s, maxb=96631KB/s, mint=60002msec, maxt=60002msec

#io=表示总共完成的IO数量。基于时间的测试场景下,此值为变量(时间越长读写次数越多);在基于容量的测试场景下,此值匹配size参数大小(最多只会读写文件大小的size)。

#aggrb是所有进程/设备的汇总带宽。

#minb/maxb表示测量到的最小/最大带宽。

#mint/maxt表示测试的最短和最长耗时。基于时间的测试场景下,匹配runtime参数(基本一致),基于容量的测试,是一个变量(随时间大小变化)。

3.3 fio的job文件格式

job file格式采用经典的ini文件,[]中的值表示job name,可以采用任意的ASCII字符,‘global’除外,global有特殊的意义。Global section描述了job file中各个job的默认配置值。一个job section可以覆盖global section中的参数,一个job file可以包含几个global section.一个job只会受到它上面的global section的影响。‘;’和‘#’可以用作注释

例子1:两个进程,分别从一个从128MB文件中,随机读的job file.

#global为全局配置,对每个job都生效

[global]

rw=randread

size=128m

[job1]

#这里的job名为job1,如果job1里面也定义rw,则会覆盖global中的rw的值

#rw=randwrite

[job2]

#rw=rw

#–end job file–

job1和job2 section是空的,因为所有的描述参数是共享的。没有给出filename=选项,fio会为每一个job创建一个文件名,如果用命令写,则是:

fio –name=global –rw=randread –size=128m –name=job1 –name=job2

例子2多个进程随机写文件的实例

;–start job file —

[random-writers]

ioengine=libaio

iodepth=4

rw=randwrite

bs=32k

direct=0

size=64m

numjobs=4

;–end job file–

这个例子没有global section,只有一个job section.

上一个实例的说明:采用async,每一个文件的队列长度为4,采用随机写,采用32k的块,采用非direct io,共有4个进程,每个进程随机写64M的文件。也可以采用下面的命令:

fio –name=random-writers –ioengine=libaio –iodepth=4 –rw=randwrite –bs=32k –direct=0 –size=64m –numjobs=4

3.4 环境变量(参数化)

在job file中支持环境变量扩展。类似于${VARNAME}可以作为选项的值(在=号右边)

例子:

#如下是job配置文件

;–start job files–

[random-writers]

rw=randwrite

size=${SIZE}

numjobs=${NUMJOBS}

;–end job file–

如果执行:

export SIZE=64m  NUMJOBS=4 fio jobfile,fio

该文件将被扩展为

;–start job file–

[random-writers]

rw=randwrite

size=64m

numjobs=4

;–end job file–

Tips:

fio有一些保留keywords,在内部将其替换成合适的值,这些keywords是:

$pagesize   当前系统的页大小

$mb_memory 系统的总内存的大小,以MB为单位

$ncpus 在线有效的cpu

这引起在命令行中和job file中都可以用,当job运行的时候,会自动的用当前系统的徝进行替换。支持简单的数学计算,如:

size=8*$mb_memory

也就是说我们尽量不要用这些保留关键字进行变量命名

3.5 FIO的JOB配置文件实例

[global]

#定义了全局的默认配置,其中参数化了IODEPTH,NUMJOBS,SIZE,BS,MNT_POINT,RUNTIME,SIZE

iodepth=${IODEPTH}

numjobs=${NUMJOBS}

size=${SIZE}

bs=${BS}

directory=${MNT_POINT}

runtime=${RUNTIME}  ;e.g 10, 10m; default to seconds

time_based=1

randrepeat=1

ioengine=libaio

direct=1

sync=0

fdatasync=0

group_reporting=1

filename=qfs_fio_test_file_${SIZE}

[write]

#顺序写场景

name=qfs_write_${SIZE}

rw=write

[read]

#顺序读场景

name=qfs_read_${SIZE}

rw=read

[randread]

#随机读场景

name=qfs_randread_${SIZE}

rw=randread

[randwrite]

#随机写场景

name=qfs_randwrite_${SIZE}

rw=randwrite

[rw]

#混合读写场景,读写比为7:3,将读写结果最后合并统计(MIXED)

name=qfs_rw_${SIZE}

rw=rw

rwmixread=70

unified_rw_reporting=1

[randrw]

#随机读写场景,读写比为7:3,将读写结果最后合并统计(MIXED)

name=qfs_randrw_${SIZE}

rw=randrw

rwmixread=70

unified_rw_reporting=1

3.6 FIO脚本编写

#!/bin/bash

# trap Ctrl-C and call ctrl_c()

trap ctrl_c INT

#用于捕获SIGKILL,强行中止本脚本

function ctrl_c() {

        echo "** Trapped Interupt Signal, Exit. **"

        exit 

}

if [[ $# ==  ]] || [[ $ == '-h' ]]

then

    echo "sh $0 write 128 16 1g 4k 60s /mnt/test_fio_4k"

else

    #这里的参数传递:

    #TYPE:write,read,rw,randwrite,randread,randrw

    #JOB_FILE:qfs.fio,即3.5所示的文件

    #MNT_POINT:/mnt/ccg/xxx_file,即进行读写测试的文件路径

    #IODEPTH:

    #NUMJOBS:最大16进程进行操作

    #SIZE:测试的文件大小

    #BS:块大小

    #RUNTIME:60s

    #JOB_FILE:qfs.fio

    export TYPE=$  JOB_FILE=qfs.fio MNT_POINT=$  IODEPTH=$ NUMJOBS=$ SIZE=$ BS=$ RUNTIME=$; fio --section=$TYPE $JOB_FILE --output="output/qfs_fio-$IODEPTH-$NUMJOBS-$SIZE-$BS-$TYPE.output"

fi

四、参考资料

 

云计算&存储测试:FIO工具入门与实战的更多相关文章

  1. 使用FIO工具测试块存储性能

    Linux实例和Windows实例都推荐使用FIO工具测试块存储性能.   说明 您也可以使用其他工具测试块存储性能,但不同工具测试出来的硬盘基准性能会有差异,如dd.sysbench.iometer ...

  2. 磁盘测试工具FIO工具安装和使用方法

    一.FIO工具安装: 1.查看fio是否安装 [root@localhost /]#rpm –qa|grep fio 2.源码安装(推荐) 官网地址:http://freecode.com/proje ...

  3. 数据库技术丛书:SQL Server 2016 从入门到实战(视频教学版) PDF

    1:书籍下载方式: SQL Server2016从入门到实战 PDF 下载  链接:https://pan.baidu.com/s/1sWZjdud4RosPyg8sUBaqsQ 密码:8z7w 学习 ...

  4. Elasticsearch全文检索工具入门

    Elasticsearch全文检索工具入门: 1.下载对应系统版本的文件 elasticsearch-2.4.0.zip 1.1运行elasticsearch-2.4.0\elasticsearch- ...

  5. 学习Vue 入门到实战——学习笔记

    闲聊: 自从进了现在的公司,小颖就再没怎么接触vue了,最近不太忙,所以想再学习下vue,就看了看vue相关视频,顺便做个笔记嘻嘻. 视频地址:Vue 入门到实战1.Vue 入门到实战2 学习内容: ...

  6. Ionic 入门与实战之第三章:Ionic 项目结构以及路由配置

    原文发表于我的技术博客 本文是「Ionic 入门与实战」系列连载的第三章,主要对 Ionic 的项目结构作了介绍,并讲解了Ionic 中的路由概念以及相关配置. 原文发表于我的技术博客 1. Ioni ...

  7. Ionic 入门与实战之第二章第二节:Ionic 环境搭建之 Ionic Lab 使用

    原文发表于我的技术博客 本文是「Ionic 入门与实战」系列连载的第二章第二节,主要对 Ionic Lab 工具作了介绍,并讲解了其使用方法,这也是一个开发 Ionic 比较好的调试工具. 原文发表于 ...

  8. React.js 入门与实战之开发适配PC端及移动端新闻头条平台课程上线了

    原文发表于我的技术博客 我在慕课网的「React.js 入门与实战之开发适配PC端及移动端新闻头条平台」课程已经上线了,文章中是目前整个课程的大纲,以后此课程还会保持持续更新,此大纲文档也会保持更新, ...

  9. Python测试 ——开发工具库

    Web UI测试自动化 splinter - web UI测试工具,基于selnium封装. selenium - web UI自动化测试. mechanize- Python中有状态的程序化Web浏 ...

随机推荐

  1. Scala 基础(七):Scala 运算符

    1 算术运算符 算术运算符(arithmetic)是对数值类型的变量进行运算的,在Scala程序中使用的非常多. 细节说明: 1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留 ...

  2. scrapy 基础组件专题(六):自定义命令

    写好自己的爬虫项目之后,可以自己定制爬虫运行的命令. 一.单爬虫 在项目的根目录下新建一个py文件,如命名为start.py,写入如下代码: from scrapy.cmdline import ex ...

  3. 数据可视化之PowerQuery篇(十三)Power BI总计行错误,这个技巧一定要掌握

    https://zhuanlan.zhihu.com/p/102567707 ​前一段介绍过一个客户购买频次统计的案例: Power BI 数据分析应用:客户购买频次分布. 我并没有在文章中显示总计行 ...

  4. Python Ethical Hacking - VULNERABILITY SCANNER(7)

    VULNERABILITY_SCANNER How to discover a vulnerability in a web application? 1. Go into every possibl ...

  5. 【JVM之内存与垃圾回收篇】堆

    堆 堆的核心概念 堆针对一个 JVM 进程来说是唯一的,也就是一个进程只有一个 JVM,但是进程包含多个线程,他们是共享同一堆空间的. 一个 JVM 实例只存在一个堆内存,堆也是 Java 内存管理的 ...

  6. 拿下Netty这座城,从现在开始!

    你好,我是彤哥,技术公号主"彤哥读源码"的运营者. 其实,我刚学习Netty的时候,也是很迷茫的,直到有一天,一个同事收到了阿里的offer,他要去阿里做中台了,临走前他偷偷地告诉 ...

  7. Zookeeper ----- 系统模型

    数据模型 Zookeeper的数据模型与文件系统非常相似,唯一不同的它的每个节点(ZNode)都可以存放数据,无论父节点还是子节点. 事务ID 即前面提到的ZXID.对每个事务请求,Zookeeper ...

  8. 前端学习(六):body标签(四)

    进击のpython ***** 前端学习--body标签 关于前面的都是大部分的标签内容 但是就像衣服一样,除了要有,还要放到适当的位置 我们先来看看一下网页的布局: 就可以看出来,网页都是一块一块的 ...

  9. MySQL 删除表中所有数据

    方法一:使用 delete from [表名]    生成日志 方法二:使用 truncate table [表名]    无日志生成 两种方式删除后再插入数据,第一条id的值不一样 方法一: 方法二 ...

  10. spring boot 项目连接数据库查询数据过程

    spring boot 项目搭建 pom.xml <?xml version="1.0" encoding="UTF-8"?> <projec ...