Fio工具详解【强大的IO性能压测工具】

发布时间 2023-09-02 15:52:57作者: yooooooo

Fio压测工具操作

fio -name=iouring_test -filename=/mnt/vdd/testfile -iodepth=128 -thread -rw=randread -ioengine=io_uring -sqthread_poll=1 -direct=1 -bs=4k -size=10G -numjobs=1 -runtime=120 -group_reporting

常用参数

[time]
runtime=time

  • 告诉fio在指定的时间段后终止处理。很难确定指定作业将运行多长时间,因此此参数可以方便的将总运行时间限制为给定时间。当省略单位时间,该数值以秒为单位进行解释。

time_based

  • 如果设置,即使文件被完全读取或写入,fio也将在指定的运行期间运行。它会在runtime准许时间内多次循环相同的工作负载。

[I/O tpye]
direct=bool

​ 是否使用 direct io,测试过程不使用OS 自带的buffer,使测试磁盘的结果更真实。Linux读写的时候,内核维护了缓存,数据先写到缓存,后面在后台写到SSD。读的时候也优先读缓存里的数据。这样速度可以加快,但是一旦掉电,缓存里的数据就没有了。所以有一种模式叫做direct io,跳过缓存,直接读写SSD。

rw=randwrite

测试随机写的I/O:

​ 顺序IO是指读写操作的访问地址顺序连接,顺序的操作磁道搜索时间显著减少,因为磁头可以以最小的移动访问下一块。【数据备份和日志记录都是顺序IO业务】

​ 随机IO是指读写操作时间连续,但是访问地址不连续,随机分布在磁盘的地址空间中。产生随机IO的业务有OLTP服务,SQL等。

rw=randrw
​ 测试随机写或者读的IO

rwmixwrite=int

​ 在混合读写模式下,写占用30%

[Blocks size]
bs=int

​ 单次IO的块文件大小为16k

bsrange=1k-4k,2k-8k,1k-4k

​ 指定数据块的大小范围,可以为读取、写入和修剪指定逗号分割的范围。

size=5G

​ 每个线程读写的数据量是5GB

[Job description]

name=str

​ 一个任务的名字,重复了也没关系。如果fio -name=job1 -name=job2,建立了两个任务,共享-name=job1之前的参数。-name=job1之后的就是job2任务独有的参数。

numjobs=int

​ 创建此作业的指定数量的克隆。每个作业克隆都作为一个独立的线程或者进程产生(执行相同工作的进程或者线程)。每个Job(任务)开1个线程,有多少 -name 就开多少个线程。所以最终线程数 = 任务数 (-name 的数量) * numjiobs。

filename=str

​ 测试文件的名称。指定相对路径或者绝对路径。没有的话会自行创建。

[Threads, processes and job synchronization]

thread

​ Fio默认使用fork创建作业,如果给出此选项,将会以pthread_create(3) 创建作业。使用fork创建线程的开销比较大。

threads=int

​ 指定线程的数量

[I/O engine]

ioengine=<str>

​ str: sync 基本的同步·读写操作,参考fsync和fdatasync

​ str:psync 基于 pread(2) 或者 pwrite(2) 进行IO操作。

​ str:vsync

​ str:pvsync

​ str:pvsync2:

​ str:io_uring 快速的Linux原生异步I/O。支持直接和缓冲IO操作。

​ str:io_uring_cmd 用于传递命令的快速Linux本机异步I/O。

​ str:libaio linux异步I/O。注意:Linux可能只支持具有非缓冲I/O的排队行为(设置为direct=1或buffered=0: rbd:通过librbd直接访问CEPH Rados

userspace_reap:[libaio]

​ 通常,在使用libaio引擎的情况下,fio将使用io_getevents(2)系统调用来获取新返回的事件。打开此标志后,将直接从客户空间读取AIO环以获取事件。提高异步IO的收割速度。当轮询至少0个事件时候,收割模式才会启动。(iodepth_batch_complete=0

[IO depth]

iodepth=int

​ 队列的深度。在异步模式下,CPU不能一直无限的发命令到SSD。比如SSD执行读写如果发生了卡顿,那有可能系统会一直不停的发命令,几千个,甚至几万个,这样一方面SSD扛不住,另一方面这么多命令会很占内存,系统也要挂掉了。

iodepth 技巧
大致把延迟分为两部分,第一部分是读写本身需要的时间ts,第二部分是路上的网络、上下文切换时间tl。
iodepth可降低tl占比,提高ts占比:
iodepth可以批量提交请求,所以可以降低上下文切换的次数。
当ts本身占比很高的时候,那就没有提升的空间了。
如果ts占比较低,通过提高iodepth就可以提升iops。

[Buffers and memory]

lockmem=int

​ 使用mlock(2)固定指定数量的内存。可用于模拟较小的内存量。只使用指定内存进行测试。

zero_buffers

​ 用全零初始化缓冲区。默认值:用随机数据填充缓冲区。

[Target file/device]

nrfiles=int

​ 用于此作业文件数。默认为1.除非文件大小明确指定大小,否则文件大小将是数据量除以nrfiles的大小。文件是为每个线程单独创建的。默认情况下,每个文件的名称中都有一个文件编号。

opendir=str

​ 让fio递归的添加目录下和子目录下的所有文件。

[command line options]

--output=filename

​ 输出日志信息到指定的文件。

--output-format=format

​ 指定输出文件的格式。将日志格式设置为normal、terse、json 或 json+。可以选择多种格式,以逗号分隔。terse 是一种基于 CSV 的格式。json+ 类似于 json,只是它添加了延迟存储桶的完整转储。

[Measurements and reporting]

group_reporting

​ 关于显示结果的,汇总每个进程的信息。

stats=bool

​ 默认情况下,fio收集并显示所有运行的作业的最终输出结果。如果此选项设置为0,则fio将在最终统计输出中忽略它。

write_bw_log=str

​ 如果给定,为此作业编写带宽日志。可以用于存储作业在其生命周期内的宽带数据。

write_lat_log=str

​ 与write_bw_log相同,只是此选项创建 I/O 提交(例如,name_slat.x.log)、完成(例如,name_clat.x.log)和总(例如,name_lat.x.log)延迟文件。有关文件名格式的详细信息,请参阅write_bw_log,并了解数据在文件中的结构,请参阅日志文件格式。

write_hist_log=str

​ 与write_bw_log相同,但改为写入I/O完成延迟直方图(例如 name_hist.x.log)。

fio压测示例

#针对io_uring的fixedufs特性
fio -threads=8 -size=10G -name=test -group_reporting -filename=./io.tmp -runtime=60 --ioengine=io_uring --iodepth=512 --fixedbufs 

#针对io_uring的sqthread_poll特性
fio -threads=8 -size=10G -name=test -group_reporting -filename=./io.tmp -runtime=60 --ioengine=io_uring --iodepth=512 --sqthread_poll 1

日志数据说明

[root@docker sda]# fio -ioengine=libaio -bs=4k -direct=1 -thread -rw=read -filename=/dev/sda -name="BS 4KB read test" -iodepth=16 -runtime=60
BS 4KB read test: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=16
fio-3.7
Starting 1 thread
Jobs: 1 (f=1): [R(1)][100.0%][r=89.3MiB/s,w=0KiB/s][r=22.9k,w=0 IOPS][eta 00m:00s]
BS 4KB read test: (groupid=0, jobs=1): err= 0: pid=18557: Thu Apr 11 13:08:11 2019
   read: IOPS=22.7k, BW=88.5MiB/s (92.8MB/s)(5313MiB/60001msec)
    slat (nsec): min=901, max=168330, avg=6932.34, stdev=1348.82
    clat (usec): min=90, max=63760, avg=698.08, stdev=240.83
     lat (usec): min=97, max=63762, avg=705.17, stdev=240.81
    clat percentiles (usec):
     |  1.00th=[  619],  5.00th=[  627], 10.00th=[  627], 20.00th=[  635],
     | 30.00th=[  635], 40.00th=[  685], 50.00th=[  717], 60.00th=[  725],
     | 70.00th=[  725], 80.00th=[  725], 90.00th=[  734], 95.00th=[  816],
     | 99.00th=[ 1004], 99.50th=[ 1020], 99.90th=[ 1057], 99.95th=[ 1057],
     | 99.99th=[ 1860]
   bw (  KiB/s): min=62144, max=91552, per=100.00%, avg=90669.02, stdev=3533.77, samples=120
   iops        : min=15536, max=22888, avg=22667.27, stdev=883.44, samples=120
  lat (usec)   : 100=0.01%, 250=0.01%, 500=0.01%, 750=93.85%, 1000=5.14%
  lat (msec)   : 2=0.99%, 4=0.01%, 10=0.01%, 50=0.01%, 100=0.01%
  cpu          : usr=5.35%, sys=23.17%, ctx=1359692, majf=0, minf=17
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=100.0%, 32=0.0%, >=64=0.0%
     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.1%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=1360097,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=16
 
Run status group 0 (all jobs):
   READ: bw=88.5MiB/s (92.8MB/s), 88.5MiB/s-88.5MiB/s (92.8MB/s-92.8MB/s), io=5313MiB (5571MB), run=60001-60001msec
 
Disk stats (read/write):
  sda: ios=1357472/0, merge=70/0, ticks=949141/0, in_queue=948776, util=99.88%