第四节:测试硬盘读写

方式一(了解即可):基于dd命令,dd命令可以通用,基本上×NIX系统上都有安装,但不够专业,也没有考虑到缓存和物理读的区分,测试的数据也是仅作参考,不能算是权威,平时可以使用来对磁盘的读写速度作一个简单的评估

# 基于/dev/null设备测试读
[root@aliyun ~]# time dd if=/dev/vda1 of=/dev/null bs=8k count=10000  
# 测试写,如果要测试实际速度 还要在末尾加上 oflag=direct测到的才是真实的IO速度
[root@aliyun ~]# time dd if=/dev/vda1 of=/a.txt bs=8k count=10000

方式二(推荐使用):fio
FIO是测试IOPS的非常好的工具,用来对磁盘进行压力测试和验证。磁盘IO是检查磁盘性能的重要指标,可以按照负载情况分成照顺序读写,随机读写两大类。FIO是一个可以产生很多线程或进程并执行用户指定的特定类型I/O操作的工具,FIO的典型用途是编写和模拟的I/O负载匹配的作业文件。也就是说FIO 是一个多线程io生成工具,可以生成多种IO模式,用来测试磁盘设备的性能(也包含文件系统:如针对网络文件系统 NFS 的IO测试)。

另外还有GFIO则是FIO的图形监测工具,它提供了图形界面的参数配置,和性能监测图像。

fio在github上的坐标:https://github.com/axboe/fio
安装

yum install fio libaio-devel -y  #后者为异步io引擎依赖包

使用示例

fio -name=mytest -direct=1 -rw=read -bs=4k -size=5G -ioengine=libaio -iodepth=64 -thread -numjob=1 -filename=/dev/sda -runtime=60

简单参数解释
-name=mytest 指定本次测试任务名,自定义即可
-direct=1 代表从内存直接写入磁盘,即采用O_DIECT的方式,规避buffer写缓冲区带来的影响
-rw=read 代表顺序读取
-bs=4k -size=5G 代表单次IO块大小为4k,总共读取5G数据
-ioengine=libaio 代表异步读取,提交完io请求后可以继续提交下一个
-iodepth=64 则代表总共提交了多少个io请求,结合上一个参数的异步提交,此处的io提交是提交完一个立即提交下一个
-thread=1  使用pthread_create创建线程,另一种是fork创建进程。进程的开销比线程要大,一般都采用thread测试。
-numjob=1 代表启动一个任务来执行上述的IO测试,一个任务代表一个线程

-filename=/dev/sda代表测试文件名称,通常选择需要测试的盘的data目录。
-runtime=60 代表测试多长时间,测试时间为60秒,如果不写则一直将5g文件分4k每次写完为止。

更多参数

参数说明:
direct=1            是否使用directIO,测试过程绕过OS自带的buffer,使测试磁盘的结果更真实。Linux读写的时候,内核维护了缓存,数据先写到缓存,后面再后台写到SSD。读的时候也优先读缓存里的数据。这样速度可以加快,但是一旦掉电缓存里的数据就没了。所以有一种模式叫做DirectIO,跳过缓存,直接读写SSD。 
rw=randwrite        测试随机写的I/O
rw=randrw           测试随机写和读的I/O

bsrange=512-2048    同上-bs=4k类似,此处为指定数据块的大小范围

numjobs=1           每个job(任务)开1个线程,这里用了几,后面每个用-name指定的任务就开几个线程测试。所以最终线程数=任务数(几个name=jobx)* numjobs。 
name=job1:         一个任务的名字,重复了也没关系。如果fio -name=job1 -name=job2,建立了两个任务,共享-name=job1之前的参数。-name之后的就是job2任务独有的参数。 

ioengine=libaio     指定io引擎使用libaio方式。libaio:Linux本地异步I/O。请注意,Linux可能只支持具有非缓冲I/O的排队行为(设置为“direct=1”或“buffered=0”);rbd:通过librbd直接访问CEPH Rados 
iodepth=16          队列的深度为16.在异步模式下,CPU不能一直无限的发命令到SSD。比如SSD执行读写如果发生了卡顿,那有可能系统会一直不停的发命令,几千个,甚至几万个,这样一方面SSD扛不住,另一方面这么多命令会很占内存,系统也要挂掉了。这样,就带来一个参数叫做队列深度。
Block Devices(RBD) 无需使用内核RBD驱动程序(rbd.ko)。该参数包含很多ioengine,如:libhdfs/rdma等
rwmixwrite=30       在混合读写的模式下,写占30%
group_reporting     关于显示结果的,汇总每个进程的信息。
此外
lockmem=1g          只使用1g内存进行测试。
zero_buffers        用0初始化系统buffer。
nrfiles=8           每个进程生成文件的数量。

磁盘读写常用测试点,需要储备知识:顺序IO与随即IO:https://egonlin.com/?p=7230

1. Read=100%  Ramdon=100%   rw=randread   (100%随机读)
2. Read=100%  Sequence=100% rw=read      (100%顺序读)
3. Write=100% Sequence=100% rw=write     (100%顺序写)
4. Write=100% Ramdon=100%   rw=randwrite (100%随机写)
5. Read=70%   Sequence=100% rw=rw, rwmixread=70, rwmixwrite=30
(70%顺序读,30%顺序写)
6. Read=70%   Ramdon=100% rw=randrw, rwmixread=70, rwmixwrite=30
(70%随机读,30%随机写)

示例
100%随机,100%读, 4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=rand_100read_4k

100%随机,100%写, 4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=rand_100write_4k

100%顺序,100%读 ,4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=sqe_100read_4k

100%顺序,100%写 ,4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=sqe_100write_4k

100%随机,70%读,30%写 4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=randrw_70read_4k

FIO测试实例

[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%

FIO结果解读

结果解读:
test: (g=0): rw=write, bs=1M-1M/1M-1M/1M-1M, ioengine=libaio, iodepth=16
fio-2.8
Starting 1 process
Jobs: 1 (f=1): [W(1)] [100.0% done] [0KB/68198KB/0KB /s] [0/66/0 iops] [eta 00m:00s]
test: (groupid=0, jobs=1): err= 0: pid=4676: Thu Apr  7 17:22:37 2016
  write: io=20075MB, bw=68464KB/s, iops=66, runt=300255msec           #执行多少IO,平均带宽,线程运行时间
    slat (usec): min=51, max=5732, avg=291.11, stdev=262.47           #提交延迟
    clat (usec): min=1, max=2235.8K, avg=239043.28, stdev=153384.41   #完成延迟
     lat (usec): min=367, max=2235.9K, avg=239337.72, stdev=153389.57 #响应时间
    clat percentiles (usec):
     |  1.00th=[  221],  5.00th=[  442], 10.00th=[ 1004], 20.00th=[108032],
     | 30.00th=[228352], 40.00th=[248832], 50.00th=[257024], 60.00th=[268288],
     | 70.00th=[280576], 80.00th=[301056], 90.00th=[342016], 95.00th=[477184],
     | 99.00th=[806912], 99.50th=[864256], 99.90th=[1122304], 99.95th=[1171456],
     | 99.99th=[1646592]
    bw (KB  /s): min=  170, max=204800, per=100.00%, avg=68755.07, stdev=27034.84
    lat (usec) : 2=0.01%, 4=0.13%, 50=0.06%, 100=0.26%, 250=1.04%
    lat (usec) : 500=4.53%, 750=2.61%, 1000=1.33%
    lat (msec) : 2=1.18%, 4=0.15%, 10=0.77%, 20=0.77%, 50=1.50%
    lat (msec) : 100=4.43%, 250=23.48%, 500=53.23%, 750=3.09%, 1000=1.30%
    lat (msec) : 2000=0.19%, >=2000=0.01%
  cpu          : usr=0.03%, sys=2.11%, ctx=19066, majf=0, minf=7
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=103.8%, 32=0.0%, >=64=0.0%   #io队列
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%  #单个IO提交要提交的IO数
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.1%, 32=0.0%, 64=0.0%, >=64=0.0%  
     issued    : total=r=0/w=20060/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=16    #IO完延迟的分布

Run status group 0 (all jobs):
  WRITE: io=20075MB, aggrb=68464KB/s(group总带宽), minb=68464KB/s(最小平均带宽), maxb=68464KB/s(最大平均带宽), mint=300255msec(group中线程的最短运行时间), maxt=300255msec(group中线程的最长运行时间)

Disk stats (read/write):
  sda: ios=23/41769(所有group总共执行的IO数), merge=0/149(总共发生的IO合并数), ticks=706/9102766(Number of ticks we kept the disk busy), in_queue=9105836(花费在队列上的总共时间), util=100.00%(磁盘利用率)

io=执行了多少M的IO
bw=平均IO带宽
iops=IOPS
runt=线程运行时间
slat=提交延迟,提交该IO请求到kernel所花的时间(不包括kernel处理的时间)
clat=完成延迟, 提交该IO请求到kernel后,处理所花的时间
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=磁盘利用率

其他测试磁盘IO的方式可以自行了解,如hdparm

上一篇
下一篇
Copyright © 2022 Egon的知识星球 egonlin.com 版权所有 帮助IT小伙伴学到真正的技术