前言

fio 是测试 IOPS 的非常好的工具,用来对硬件进行压力测试和验证,支持 13 种不同的 I/O 引擎,包括: sync,mmap, libaio, posixaio, SG v3, splice, null, network, syslet, guasi, solarisaio 等等。

简单好用的磁盘性能测试工具


更新记录

2015 年 10 月 20 日 - 初稿

阅读原文 - https://liaojiaxin158.github.io/post/fio/

扩展阅读

fio - http://freecode.com/projects/fio
云主机磁盘 I/O 基准性能测试 - https://docs.ucloud.cn/testdata/io_uhost.html
fio man - http://linux.die.net/man/1/fio


测试准备

工具:fio - Flexible IO Tester

官方网站:

http://freecode.com/projects/fio

http://brick.kernel.dk/snaps/

注意 : 性能测试建议直接通过写裸盘的方式进行测试,会得到较为真实的数据。但直接测试裸盘会破坏文件系统结构,导致数据丢失,请在测试前确认磁盘中数据已备份。

CentOS 可以直接使用 yum 安装

1
2
3
4
5
6
7
8
#yum 安装
yum install libaio-devel fio
# 手动安装
yum install libaio-devel
wget http://brick.kernel.dk/snaps/fio-2.2.10.tar.gz
tar -zxvf fio-2.2.10.tar.gz
cd fio-2.2.10
make $ make install

fio 用法

fio 分顺序读,随机读,顺序写,随机写,混合随机读写模式。

filename: 指定文件 (设备) 的名称。可以通过冒号分割同时指定多个文件,如 filename=/dev/sda:/dev/sdb。

directory: 设置 filename 的路径前缀。在后面的基准测试中,采用这种方式来指定设备。

name: 指定 job 的名字,在命令行中表示新启动一个 job。

direct: bool 类型,如果设置成 true (1),表示不使用 io buffer。

ioengine: I/O 引擎,现在 fio 支持 19 种 ioengine。默认值是 sync 同步阻塞 I/O,libaio 是 Linux 的 native 异步 I/O。关于同步异步,阻塞和非阻塞模型可以参考文章“使用异步 I/O 大大提高应用程序的性能”。
http://www.ibm.com/developerworks/cn/linux/l-async/

iodepth: 如果 ioengine 采用异步方式,该参数表示一批提交保持的 io 单元数。该参数可参考文章“Fio 压测工具和 io 队列深度理解和误区”。
http://blog.yufeng.info/archives/2104

rw: I/O 模式,随机读写,顺序读写等等。

bs: I/O block 大小,默认是 4k。

size: 指定 job 处理的文件的大小。

numjobs: 指定 job 的克隆数(线程)。

time_based: 如果在 runtime 指定的时间还没到时文件就被读写完成,将继续重复知道 runtime 时间结束。

runtime: 指定在多少秒后停止进程。如果未指定该参数,fio 将执行至指定的文件读写完全完成。

group_reporting: 当同时指定了 numjobs 了时,输出结果按组显示。

fio 参数说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
filename=/dev/sdb1   # 测试文件名称,通常选择需要测试的盘的 data 目录
direct=1 # 测试过程绕过机器自带的 buffer。使测试结果更真实
rw=randwrite # 测试随机写的 I/O
rw=randrw # 测试随机写和读的 I/O
bs=16k # 单次 io 的块文件大小为 16k
bsrange=512-2048 # 同上,提定数据块的大小范围
size=5G # 本次的测试文件大小为 5g,以每次 4k 的 io 进行测试
numjobs=30 # 本次的测试线程为 30 个
runtime=1000 # 测试时间 1000 秒,如果不写则一直将 5g 文件分 4k 每次写完为止
ioengine=psync #io 引擎使用 psync 方式
rwmixwrite=30 # 在混合读写的模式下,写占 30%
group_reporting # 关于显示结果的,汇总每个进程的信息

lockmem=1G # 只使用 1g 内存进行测试
zero_buffers # 用 0 初始化系统 buffer
nrfiles=8 # 每个进程生成文件的数量

# 顺序读
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest

# 顺序写
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest

# 随机读
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest

# 随机写
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest

# 混合随机读写
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=100 -group_reporting -name=mytest -ioscheduler=noop

# 复制下面的配置内容,将 directory=/path/to/test 修改为你测试硬盘挂载目录的地址,并另存为 fio.conf

[global]
ioengine=libaio
direct=1
thread=1
norandommap=1
randrepeat=0
runtime=60
ramp_time=6
size=1g
directory=/path/to/test

[read4k-rand]
stonewall
group_reporting
bs=4k
rw=randread
numjobs=8
iodepth=32

[read64k-seq]
stonewall
group_reporting
bs=64k
rw=read
numjobs=4
iodepth=8

[write4k-rand]
stonewall
group_reporting
bs=4k
rw=randwrite
numjobs=2
iodepth=4

[write64k-seq]
stonewall
group_reporting
bs=64k
rw=write
numjobs=2
iodepth=4

# 测试
fio fio.conf

实际测试范例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# 测试混合随机读写
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=100 -group_reporting -name=mytest1

mytest1: (g=0): rw=randrw, bs=16K-16K/16K-16K/16K-16K, ioengine=psync, iodepth=1

...

mytest1: (g=0): rw=randrw, bs=16K-16K/16K-16K/16K-16K, ioengine=psync, iodepth=1

fio-2.1.2

Starting 30 threads

Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [18.8% done] [10192KB/3376KB/0KB /s] [637/211/0 iops] [eta 01m:22sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [19.8% done] [9808KB/3200KB/0KB /s] [613/200/0 iops] [eta 01m:21s]Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [34.7% done] [10496KB/3232KB/0KB /s] [656/202/0 iops] [eta 01m:06sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [35.6% done] [9680KB/3232KB/0KB /s] [605/202/0 iops] [eta 01m:05s]Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [37.6% done] [10016KB/2864KB/0KB /s] [626/179/0 iops] [eta 01m:03sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [38.6% done] [10320KB/3632KB/0KB /s] [645/227/0 iops] [eta 01m:02sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [39.6% done] [9744KB/3264KB/0KB /s] [609/204/0 iops] [eta 01m:01s]Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [63.4% done] [10224KB/3792KB/0KB /s] [639/237/0 iops] [eta 00m:37sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [64.4% done] [9184KB/3808KB/0KB /s] [574/238/0 iops] [eta 00m:36s]Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [68.3% done] [10128KB/3200KB/0KB /s] [633/200/0 iops] [eta 00m:32sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [69.3% done] [9872KB/3184KB/0KB /s] [617/199/0 iops] [eta 00m:31s]Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [71.3% done] [10528KB/2624KB/0KB /s] [658/164/0 iops] [eta 00m:29sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [72.3% done] [9696KB/2752KB/0KB /s] [606/172/0 iops] [eta 00m:28s]Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [73.3% done] [10624KB/2912KB/0KB /s] [664/182/0 iops] [eta 00m:27sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [74.3% done] [9312KB/2832KB/0KB /s] [582/177/0 iops] [eta 00m:26s]Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [95.0% done] [10128KB/3792KB/0KB /s] [633/237/0 iops] [eta 00m:05sJobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [96.0% done] [8320KB/3904KB/0KB /s] [520/244/0 iops] [eta 00m:04s]Jobs: 30 (f=30):

[mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm] [100.0% done] [9264KB/3536KB/0KB /s] [579/221/0 iops] [eta 00m:00s]

mytest1: (groupid=0, jobs=30): err= 0: pid=17792: Tue Nov 12 10:55:58 2013

read : io=948896KB, bw=9475.1KB/s, iops=592, runt=100138msec

clat (usec): min=67, max=796794, avg=49878.72, stdev=59636.00

lat (usec): min=68, max=796794, avg=49879.01, stdev=59636.00

clat percentiles (msec):

| 1.00th=[ 4], 5.00th=[ 7], 10.00th=[ 9], 20.00th=[ 12],

| 30.00th=[ 16], 40.00th=[ 22], 50.00th=[ 29], 60.00th=[ 39],

| 70.00th=[ 53], 80.00th=[ 76], 90.00th=[ 120], 95.00th=[ 165],

| 99.00th=[ 293], 99.50th=[ 351], 99.90th=[ 494], 99.95th=[ 553],

| 99.99th=[ 701]

bw (KB /s): min= 20, max= 967, per=3.38%, avg=320.53, stdev=116.83

write: io=380816KB, bw=3802.1KB/s, iops=237, runt=100138msec

clat (usec): min=64, max=120607, avg=1801.07, stdev=5409.97

lat (usec): min=65, max=120610, avg=1803.86, stdev=5409.96

clat percentiles (usec):

| 1.00th=[ 69], 5.00th=[ 73], 10.00th=[ 77], 20.00th=[ 81],

| 30.00th=[ 84], 40.00th=[ 87], 50.00th=[ 90], 60.00th=[ 113],

| 70.00th=[ 724], 80.00th=[ 3248], 90.00th=[ 4384], 95.00th=[ 5344],

| 99.00th=[33536], 99.50th=[41728], 99.90th=[59136], 99.95th=[68096],

| 99.99th=[112128]

bw (KB /s): min= 17, max= 563, per=3.52%, avg=133.68, stdev=75.04

lat (usec) : 100=16.41%, 250=3.47%, 500=0.10%, 750=0.12%, 1000=0.23%

lat (msec) : 2=0.86%, 4=4.57%, 10=13.39%, 20=16.08%, 50=22.27%

lat (msec) : 100=12.87%, 250=8.49%, 500=1.08%, 750=0.06%, 1000=0.01%

cpu : usr=0.02%, sys=0.07%, ctx=83130, majf=0, minf=7

IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.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.0%, 32=0.0%, 64=0.0%, >=64=0.0%

issued : total=r=59306/w=23801/d=0, short=r=0/w=0/d=0



Run status group 0 (all jobs):

READ: io=948896KB, aggrb=9475KB/s, minb=9475KB/s, maxb=9475KB/s, mint=100138msec, maxt=100138msec

WRITE: io=380816KB, aggrb=3802KB/s, minb=3802KB/s, maxb=3802KB/s, mint=100138msec, maxt=100138msec



Disk stats (read/write):

sda: ios=59211/24192, merge=0/289, ticks=2951434/63353, in_queue=3092383, util=99.97%

测试结果如上,主要关注 bw 和 iops 结果

bw:磁盘的吞吐量,这个是顺序读写考察的重点
iops:磁盘的每秒读写次数,这个是随机读写考察的重点

1
2
read : io=948896KB, bw=9475.1KB/s, iops=592, runt=100138msec
write: io=380816KB, bw=3802.1KB/s, iops=237, runt=100138msec

硬盘性能指标

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

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

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

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

以下是使用通用 I/O 测试工具 “fio”,并在指定数据块大小“4K、512K”、队列深度为“128” 的条件下,对 “SAS” 以及 “SSD” 这两种机型磁盘进行的 I/O 基准性能测试所得出的测试数据。

测试数据

测试 1. 顺序读 / 写 512K

测试 2. 随机读 / 写 4K

配置文件

块大小:4kb / 512kb
队列深度:128

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#fio.conf 配置

[global]
ioengine=libaio
iodepth=128
time_based
direct=1
thread=1
group_reporting
randrepeat=0
norandommap
numjobs=32
timeout=6000
runtime=120

[randread-4k]
rw=randread
bs=4k
filename=/dev/sdb # 注:/dev/sdb 是目标测试磁盘的设备名称
rwmixread=100
stonewall

[randwrite-4k]
rw=randwrite
bs=4k
filename=/dev/sdb
stonewall

[read-512k]
rw=read
bs=512k
filename=/dev/sdb
stonewall

[write-512k]
rw=write
bs=512k
filename=/dev/sdb
stonewall

# 使用方法
shell$> fio fio.conf
文章目录
  1. 1. 前言
  2. 2. 更新记录
  3. 3. 测试准备
  4. 4. fio 用法
    1. 4.1. fio 参数说明
    2. 4.2. 实际测试范例
  5. 5. 硬盘性能指标
    1. 5.1. 测试数据
    2. 5.2. 配置文件