磁盘性能分析
以下工具都为 CentOS 自带,可以通过 yum 安装
hdparm
该测试的原理是 hdparm 直接读取磁盘扇区数据,然后衡量读取速度,所以只能测试顺序读取,无法测试写入速度。
hdparm -t /dev/sdb
dd
dd 比较适合用于在所有场景下的顺序写入和读取测试,可以测试块设备,也可以测试文件系统。
顺序写入
dd if=/dev/zero of=./sample bs=1M count=1000 oflag=direct
# 注意加入 oflag=direct 绕开 OS 的 buffer/cache
顺序读取
echo 3 > /proc/sys/vm/drop_caches# /dev/null 不支持 oflag=direct,所以先 drop 一下 cache
dd if=./sample of=/dev/null bs=1M count=1000
对于超过 500MB/s 的顺序读测试,请使用 fio,之前对一个 RAID-0 组的顺序读测试发现,dd 只能跑到 500MB/s,但是 fio 可以达到 900MB/s,顺序写则与 fio 相同。
fio
fio 是一个比较专业的磁盘性能测试工具,当然,使用起来也比较复杂
测试块设备的顺序读取
fio --filename=/dev/sdc --direct=1 --rw=read --bs=1M --ioengine=libaio --iodepth=1 --numjobs=1 --runtime=10 --group_reporting --name=1m-seq-read-test
--ioengine=libaio:使用异步IO API库
--iodepth=1:异步IO同时发送的请求数为1,如果调成 2,每个线程 libaio 会同时发送两个读请求,然后等待它们的返回
--numjobs=1:线程数为 1
--runtime=10:测试时长10秒
--bs=1M:以1M的粒度读取数据
--group_reporting:将多个线程的测试结果进行整合
该测试会开启一个线程,从 /dev/sdc 块设备的起始处以 1M、1M的粒度读取块设备,读取 10 秒,
如果中途 Ctrl-C 让其停止,对测试结果不会有太大的影响,只是缩短测试时间而已。
测试块设备的随机读取
fio --filename=/dev/sdc --direct=1 --rw=randread --bs=4K --ioengine=libaio --iodepth=1 --numjobs=1 --runtime=10 --group_reporting --name=4k-rand-read-test
该测试会单线程以 4K 的粒度随机读取 /dev/sdc 数据,只是测试单线程随机 IO 能力,对于测随机 IO 的 lantency 比较有用。
如果将 numjobs 和 iodepth 都调成 16(一共会有 16*16 = 256 个并发读请求),一般可以将磁盘的 IOPS 跑满。(如果只将 iodepth 调大一点,效果会差一些)
测试结果赏析:
4k-rand-read-test: (g= 0 ): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth= 32 fio- 2.0 . 13 Starting 1 process Jobs: 1 (f= 1 ): [r] [ 100.0 % done] [627K/0K/0K /s] [ 156 / 0 / 0 iops] [eta 00m:00s] 4k-rand-read-test: (groupid= 0 , jobs= 1 ): err= 0 : pid= 2587 : Sat Aug 20 13 : 45 : 37 2016 read : io= 6384 .0KB, bw= 635977 B/s, iops= 155 , runt= 10279msec # bw(band-width), iops= 155 表示此次测试的 IOPS slat (usec): min= 8 , max= 75 , avg= 20.27 , stdev= 4.66 clat (msec): min= 2 , max= 1369 , avg= 205.66 , stdev= 200.77 # clat(complete-lantency), stdev 是正态分布的意思 lat (msec): min= 2 , max= 1369 , avg= 205.68 , stdev= 200.77 clat percentiles (msec): | 1 .00th=[ 6 ], 5 .00th=[ 13 ], 10 .00th=[ 21 ], 20 .00th=[ 41 ], | 30 .00th=[ 71 ], 40 .00th=[ 101 ], 50 .00th=[ 141 ], 60 .00th=[ 196 ], | 70 .00th=[ 260 ], 80 .00th=[ 343 ], 90 .00th=[ 474 ], 95 .00th=[ 611 ], | 99 .00th=[ 898 ], 99 .50th=[ 1004 ], 99 .90th=[ 1270 ], 99 .95th=[ 1369 ], | 99 .99th=[ 1369 ] bw (KB/s) : min= 435 , max= 694 , per= 98.70 %, avg= 612.90 , stdev= 62.44 lat (msec) : 4 = 0.38 %, 10 = 3.07 %, 20 = 5.89 %, 50 = 14.29 %, 100 = 15.98 % lat (msec) : 250 = 29.14 %, 500 = 22.62 %, 750 = 6.27 %, 1000 = 1.82 %, 2000 = 0.56 % cpu : usr= 0.31 %, sys= 0.44 %, ctx= 1636 , majf= 0 , minf= 54 IO depths : 1 = 0.1 %, 2 = 0.1 %, 4 = 0.3 %, 8 = 0.5 %, 16 = 1.0 %, 32 = 98.1 %, >= 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 = 99.9 %, 8 = 0.0 %, 16 = 0.0 %, 32 = 0.1 %, 64 = 0.0 %, >= 64 = 0.0 % issued : total=r= 1596 /w= 0 /d= 0 , short =r= 0 /w= 0 /d= 0 Run status group 0 (all jobs): READ: io=6384KB, aggrb=621KB/s, minb=621KB/s, maxb=621KB/s, mint=10279msec, maxt=10279msec Disk stats (read/write): sdc: ios= 1574 / 0 , merge= 0 / 0 , ticks= 315209 / 0 , in_queue= 321729 , util= 98.29 % |
测试块设备的顺序写入
fio --filename=/dev/sdc --direct=1 --rw=write --bs=1M --ioengine=libaio --iodepth=1 --numjobs=1 --runtime=30 --group_reporting --name=1M-seq-write-test
fio 将会以1个线程,1MB 的粒度向块设备写入数据
调整 --iodepth 到 8,相当于以 8MB 的粒度写入
调大 --numjobs,意义不大,每个线程都是独立的从头开始写,比如 --numjobs = 4 将会产生 3 次 overwrite,磁盘或 RAID 卡有可能会将这些 overwrite 合并,而只向磁盘写入一次,但从外面看,是 4 个 write 的流量
测试块设备的随机写入
注意,这个测试会破坏该块设备上的数据,请不要在有数据磁盘上作测试
fio --filename=/dev/sdc --direct=1 --rw=randwrite --bs=4K --ioengine=libaio --iodepth=1 --numjobs=1 --runtime=10 --group_reporting --name=4k-rand-write-test
可以调整 iodepth, numjobs, bs 来评估不同的测试结果
测试文件系统
只需要将 --filename 指向一个准备好的文件,即可进行测试。
如果不指定 --filename,需要指定 --size(每个线程会在当前目录创建一个指定 size 的文件,如果有 read 的测试,该文件在测试前会被创建并填充,如果只是 write 测试,则只是创建,然后 truncate 该测试文件)
fio 参考:
- https://www.linux.com/learn/inspecting-disk-io-performance-fio
- http://www.storagereview.com/fio_flexible_i_o_tester_synthetic_benchmark
- https://tobert.github.io/post/2014-04-17-fio-output-explained.html
Tips
- 打开磁盘写 cache
- hdparm -W1 /dev/sda
- RAID 性能
- RAID-1/5/6 的单线程顺序写入性能很差,可能达不到裸盘的 50%,多线程 + 高iodepth 顺序写入性能要好一点,大约可以达到单盘的 100%
- 原因是每次写入都需要同时写入不同的磁盘
- 打开 WB 之后,写入效率可以达到裸盘的 100% ~ 150%
- RAID-1/5/6 的读取性能很高,可以达到裸盘效率的 100% x 数据盘数量
- 原因是每一次读取,都可以从多块盘上将数据读取出来
- RAID-0 的读写性能相当于所有裸盘性能的聚合,即使不开启 WB 也没有任何影响
- RAID-1/5/6 的单线程顺序写入性能很差,可能达不到裸盘的 50%,多线程 + 高iodepth 顺序写入性能要好一点,大约可以达到单盘的 100%
- 使用 fio 进行顺序读/写测试时,不应该使用多线程,那样会使 IO 不连续