探索fio参数如何选择以及全方位对比HDD和SSD性能

您所在的位置:网站首页 io预读取kb数越大越好 探索fio参数如何选择以及全方位对比HDD和SSD性能

探索fio参数如何选择以及全方位对比HDD和SSD性能

2024-07-13 12:55| 来源: 网络整理| 查看: 265

由于公司要部署一套Ceph环境,趁任务并不太着急,在部署之前先对HDD和SSD进行周密的测试,以便和部署之后的Ceph服务能力(RBD、CephFS、NFS的性能)进行对比。

本文的目的是解答如下几个问题:

fio工具的参数到底该如何选择,比如:多长时间的runtime更经济?bs对测试结果有何影响?numjobs和iodepth应该设置多少?正儿八经了解一下HDD和SSD的性能。

本文有不少数据和图表,希望能够为有同样疑惑的朋友提供有益参考。(请阅读时注意BW的单位)

测试过程日志:https://github.com/get-set/fio-bench-disks-ceph/tree/master/disks

测试HDD性能

磁盘的配置如下:

磁盘为7200转3.5寸SAS机械硬盘;根据部署Ceph的官方推荐配置,每块磁盘以RAID0单盘挂在RAID卡下,RAID卡为H730 mini(拥有1G缓存),具体配置: 开启预读(read-ahead);开启写回(write-back),有电池;关闭磁盘缓存(disk-cache)。

注:

为了加快测试速度,以下测试是在两台服务器上测试的,比如有可能随机写在第一台的/dev/sdd上测试,而随机读就是在另一台的/dev/sde上测试。但是确保针对所测试参数的同一类型的IO操作的所有参数变化都是在同一块硬盘上进行的,所以请只关注各参数内的纵向测试结果即可。RAID卡有缓存,由于是为后续部署和测试Ceph做前期测试,因此以下关于磁盘的测试结果是有RAID缓存加持的,请酌情参考。 FIO参数对HDD测试的影响 1. runtime(测试时长)

一、测试目的

了解能够得到客观性能结果的最短时间,以便为后续的测试节省时间。

二、测试内容

测试4k随机读写和64k顺序读写的过程中,不同的runtime所得到的测试结果,观察从多长时间开始就可以得到稳定的测试结果。

为了观察util值(磁盘利用率),将读写分别测试。

测试脚本fio.conf:

[global] ioengine=libaio # 异步IO direct=1 # 排除OS的IO缓存机制的影响 size=5g # 每个fio进程/线程的最大读写 lockmem=1G # 锁定所使用的内存大小 directory=/mnt/sdd # XFS格式的磁盘,未直接用裸盘 iodepth=1 # 队列深度1(后续有关于参数的测试) numjobs=1 # 同时开启的fio进程/线程数为1 rw=randread # 每次测试修改该值:randread/read/randwrite/write bs=4k # 每次测试修改该值:rand对应4k,seq对应64k [job] runtime=10 # 本次测试runtime:10 20 30 40 50 60 90

测试命令:

mkdir -p logs/{runtime.4k_randread,runtime.4k_randwrite,runtime.64k_read,runtime.64k_write} # 修改不同的rw和bs值,然后执行4次如下命令(注意修改tee输出的log目录) for runtime in 10 20 30 40 50 60 90; do sed -i "/^runtime/c runtime=${runtime}" fio.conf && fio fio.conf | tee logs/runtime.4k_randread/${runtime}.log && sleep 10s; done

测试结果(IOPS和BW):

对于4k_randread、64k_read和64_write的IOPS和BW值的观察可以基本看出,从30s之后,测试结果基本趋于稳定;而4k_randwrite看不到明显的稳定区间。

再观察磁盘利用率:

通过观察util的值,发现不同的测试方法大约都能够在30秒之后得到比较稳定的结果。对于随机读来说,似乎随着时间的延长而越来越乏力,与性能结果类似。

三、测试结论

对于随机读写和顺序读写的测试来说,runtime达到30-40秒即可得到相对客观的结果,保险起见也可以时间更长。

2. bs(块大小)

一、测试目的

观察不同的块大小对读写性能的影响。

二、测试内容

测试随机读写和顺序读写的过程中,不同的bs所得到的测试结果。

为了观察util值(磁盘利用率),将读写分别测试。

测试脚本fio.conf:

[global] ioengine=libaio # 异步IO direct=1 # 排除OS的IO缓存机制的影响 size=5g # 每个fio进程/线程的最大读写 lockmem=1G # 锁定所使用的内存大小 runtime=30 # 根据上面的结论以后采用30值 directory=/mnt/sdd # XFS格式的磁盘,未直接用裸盘 iodepth=1 # 队列深度1(后续有关于参数的测试) numjobs=1 # 同时开启的fio进程/线程数为1 rw=randread # 每次测试修改该值:randread/read/randwrite/write [job] bs=4k # 本次测试bs:1k 2k 4k .. 64m

测试命令:

mkdir -p logs/{bs.randread,bs.randwrite,bs.read,bs.write} # 修改不同的rw值,然后执行4次如下命令(注意修改tee输出的log目录) for bs in 1k 2k 4k 8k 16k 32k 64k 128k 256k 512k 1m 2m 4m 8m 16m 32m 64m; do sed -i "/^bs/c bs=${bs}" fio.conf && fio fio.conf | tee logs/bs.randread/${bs}.log && sleep 10s; done

测试结果(BW和IOPS):

测试结果(BW和util):

image-20200812114056781

image-20200812114155833

三、测试结论

随着块大小的增加,读写速度会显著增加,同时IOPS显著下降,其中: 随机读写相对顺序读写来说,变化趋势相对较平缓;随机读写在小于8k以前性能变化不大,顺序读写在大于64k之后性能变化不大。 随着块大小的增加,磁盘利用率先平稳,后下降,其中: 随机读写的磁盘利用率在块大小超过256k之后会有显著提升;而顺序读写的磁盘利用率在超过256k之后缓步下滑;对于顺序读写来说,磁盘利用率保持高位,而随机读写的磁盘利用率相对较低,其中随机读的利用率低于随机写。 后续的测试,将采用4k作为随机读写的块大小,64k作为顺序读写的块大小。 3. iodepth

iodepth是队列深度,简单理解就是一批提交给系统的IO个数,由于同步的IO是堵塞的,IO操作会依次执行,iodepth一定小于1,因此该参数只有使用libaio时才有意义。因为异步的时候,系统能够在读写结果返回之前就吸纳后续的IO请求,所以loop里边可能在跑多个IO操作,然后等待结果异步返回。

libaio引擎会用这个iodepth值来调用io_setup准备个可以一次提交iodepth个IO的上下文,同时申请个io请求队列用于保持IO。 在压测进行的时候,系统会生成特定的IO请求,往io请求队列里面扔,当队列里面的IO个数达到iodepth_batch值的时候,就调用io_submit批次提交请求,然后开始调用io_getevents开始收割已经完成的IO。 每次收割多少呢?由于收割的时候,超时时间设置为0,所以有多少已完成就算多少,最多可以收割iodepth_batch_complete值个。随着收割,IO队列里面的IO数就少了,那么需要补充新的IO。 什么时候补充呢?当IO数目降到iodepth_low值的时候,就重新填充,保证OS可以看到至少iodepth_low数目的io在电梯口排队着。

一、测试目的

观察不同的iodepth大小对读写性能的影响。

二、测试内容

测试随机读写和顺序读写的过程中,不同的iodepth所得到的测试结果。

为了观察util值(磁盘利用率),将读写分别测试。

测试脚本fio.conf:

[global] ioengine=libaio # 异步IO direct=1 # 排除OS的IO缓存机制的影响 size=5g # 每个fio进程/线程的最大读写 lockmem=1G # 锁定所使用的内存大小 runtime=30 # 根据上面的结论以后采用30值 directory=/mnt/sdd # XFS格式的磁盘,未直接用裸盘 numjobs=1 # 同时开启的fio进程/线程数为1 rw=randread # 每次测试修改该值:randread/read/randwrite/write bs=4k # 每次测试修改该值:rand对应4k,seq对应64k [job] iodepth=1 # 本次测试队列深度:1 2 4 8 16(视情况增加)

测试命令:

mkdir -p logs/{iodepth.4k_randread,iodepth.4k_randwrite,iodepth.64k_read,iodepth.64k_write} # 修改不同的rw值,然后执行4次如下命令(注意修改tee输出的log目录) for iodepth in 1 2 4 8 16; do sed -i "/^iodepth/c iodepth=${iodepth}" fio.conf && fio fio.conf | tee logs/iodepth.4k_randread/${iodepth}.log && sleep 10s; done

测试结果:

4k随机读的IOPS、BW、clat、util(随机读的情况多测试了一些iodepth值):

lat是总延迟,slat是提交io到内核的延迟,clat是内核到磁盘完成之间的延迟,因此lat=slat+clat。slat通常是比较稳定的值,所以这里通过观察clat来判断IO延迟情况。

4k随机写的IOPS、BW、clat、util:

64k顺序读的IOPS、BW、clat、util:

image-20200813102037857

64k顺序写的IOPS、BW、clat、util:

三、测试结论

对于IOPS和BW来说,随着队列深度的增加,总体是呈现上涨趋势的,磁盘利用率util的趋势与这两个指标也是比较相关的: 对于4k随机读来说,在iodepth达到64之后,这两个性能指标趋于平缓;对于4k随机写来说,似乎不喜欢iodepth高于1;对于顺序读写来说,iodepth对这两个性能指标几乎没有影响。 在追求更高的IOPS和BW的同时,也要追求更低的延迟clat,随着队列深度的增加,延迟显著上升。可以基本确定iodepth值的选择: 4k随机读:32/64是不错的选择;4k随机写:1即可;64k顺序读写:1/2即可。 以上关于iodepth的值的选择可能还需numjobs的值进行调整;以上的测试结论是基于我的磁盘配置来的,也就是本文前面提到的基于单盘RAID0的磁盘配置,请酌情参考。 4. numjobs

numjobs个数指定在测试的时候同时启动的进程/线程数,主要用来测试并发IO的情况。

一、测试目的

观察不同的numjobs大小对读写性能的影响。

二、测试内容

测试随机读写和顺序读写的过程中,不同的numjobs所得到的测试结果。

为了观察util值(磁盘利用率),将读写分别测试。

测试脚本fio.conf:

[global] ioengine=libaio # 异步IO direct=1 # 排除OS的IO缓存机制的影响 size=5g # 每个fio进程/线程的最大读写 lockmem=1G # 锁定所使用的内存大小 runtime=30 # 根据上面的结论以后采用30值 directory=/mnt/sdd # XFS格式的磁盘,未直接用裸盘 rw=randread # 每次测试修改该值:randread/read/randwrite/write bs=4k # 每次测试修改该值:rand对应4k,seq对应64k iodepth=1 # 队列深度固定为1 group_reporting # 多个job合并出报告 [job] numjobs=1 # 本次测试numjobs:1 2 4 8 16

测试命令:

mkdir -p logs/{numjobs.4k_randread,numjobs.4k_randwrite,numjobs.64k_read,numjobs.64k_write} # 修改不同的rw值,然后执行4次如下命令(注意修改tee输出的log目录) for numjobs in 1 2 4 8 16; do sed -i "/^numjobs/c numjobs=${numjobs}" fio.conf && fio fio.conf | tee logs/numjobs.4k_randread/${numjobs}.log && sleep 10s; done

测试结果:

4k随机读的IOPS、BW、clat、util:

4k随机写的IOPS、BW、clat、util:

64k顺序读的IOPS、BW、clat、util:

64k顺序写的IOPS、BW、clat、util:

三、测试结论

总体来说,一个比较容易理解的情况就是,job越多,延迟越高。性能表现方面,则各有千秋: 对于4k随机读,job数量在1-16的时候有显著提升,延迟并没有明显提高,但是从16之后,性能显著下降,延迟也迅速提高;对于4k随机写,job数量从1-4,性能大约会下降一半,之后保持平稳,磁盘利用率下降为30%;对于64k顺序读,job数量从1-4,会有显著的下降,之后保持平稳,磁盘利用率也显著下降;对于64k顺序写,对numjobs参数无感。 可以基本确定numjobs值的选择: 4k随机读:16;4k随机写和64k顺序读写:1即可。

以上的测试结论是基于我的磁盘配置来的,也就是本文前面提到的基于单盘RAID0的磁盘配置,请酌情参考。

猜测对于iodepth和numjobs对4k随机读的性能影响,与RAID的read-ahead和缓存有一定关系,因为可以攒一波批量处理,不知这个猜测是否正确,有对存储比较了解的朋友欢迎留言,感谢!

5. iodepth*numjobs?

一、测试目的

iodepth可以简单理解为一次提交的IO操作的数量,numjobs可以理解为有多少个同时进行的任务。

但是,前面关于iodepth和numjobs的测试,都是在另一个指标为1的情况下进行的,虽然确定了两个参数的可选值,但是放到一起就不一定是好的选择了,因此,最后再将两个参数组合起来测试一下。

由于根据上面的分析,两个指标只是对4k随机读有助力,因此,我们只对4k随机读作测试。

二、测试内容

测试iodepth从1-64和numjobs从1-16的性能表现。测试脚本:

[global] ioengine=libaio # 异步IO direct=1 # 排除OS的IO缓存机制的影响 size=5g # 每个fio进程/线程的最大读写 lockmem=1G # 锁定所使用的内存大小 runtime=30 # 根据上面的结论以后采用30值 directory=/mnt/sdd # XFS格式的磁盘,未直接用裸盘 rw=randread # 每次测试修改该值:randread/read/randwrite/write bs=4k # 每次测试修改该值:rand对应4k,seq对应64k group_reporting # 多个job合并出报告 [job] numjobs=1 # 本次测试numjobs:1 2 4 8 16 iodepth=1 # 本次测试iodepth:1 2 4 8 16 32 64

为了得到每次的util值,我们还是用for循环的方式。

mkdir -p logs/iodepth_numjobs idx=0 for numjobs in 1 2 4 8 16; do for iodepth in 1 2 4 8 16 32 64; do sed -i "/^numjobs/c numjobs=${numjobs}" fio.conf && \ sed -i "/^iodepth/c iodepth=${iodepth}" fio.conf && \ fio fio.conf | tee logs/iodepth_numjobs/$(printf "%02d" ${idx})_n${numjobs}i${iodepth}.log && \ let idx++ && sleep 30s done done

其中,自增的idx和$(printf "%02d" ${idx})是为了方便日志文件排序。

最终测试结果如下:

三、测试结论

对于4k随机读来说,

性能总体是与iodepth成正相关的,其中iodepth为64,numjobs为1时,性能和磁盘利用率最高,延迟相对来说比较低;上面的图并不直观,其实延迟是与numjobs * iodepth的乘积成正相关的,相对来说,numjobs对延迟的影响更大,更多的并行IO任务会显著提高IO延迟。

以上的测试结论是基于我的磁盘配置来的,也就是本文前面提到的基于单盘RAID0的磁盘配置,请酌情参考,尤其是RAID卡有缓存并为磁盘配置了预读(read-ahead)。

再结合对iodepth和numjobs的测试结论,“为了测得更高的磁盘性能”,建议的参数设置是:

numjobs=14k随机读:iodepth=64/32,4k随机写/64k顺序读写:iodepth=1/2。 HDD性能结果

根据前面的测试结论,测试脚本如下:

[global] ioengine=libaio # 异步IO direct=1 # 排除OS的IO缓存机制的影响 size=5g # 每个fio进程/线程的最大读写 lockmem=1G # 锁定所使用的内存大小 runtime=30 # 根据上面的结论以后采用30值 directory=/mnt/sdd # XFS格式的磁盘,未直接用裸盘 numjobs=1 # 同时进行的任务数 iodepth=1 # 队列深度 group_reporting # 多个job合并出报告 [4k_randwrite] stonewall # 隔离各测试任务 rw=randwrite bs=4k [4k_randread] stonewall rw=randread bs=4k iodepth=64 [64k_write] stonewall rw=write bs=64k [64k_read] stonewall rw=read bs=64k

前面提到,我是两台物理机上进行的测试,不过两台物理机的RAID卡并不一样,一台是H730P mini,一台是H730 mini。区别在于二者的缓存分别是2G和1G,测试结果如下:

H730P mini(2G内存),总体利用率“64.09%”。

IOPS&BWclat(usec)4k随机写IOPS=1600, BW=6401KiB/s597.204k随机读IOPS=571, BW=2286KiB/s111941.4664k顺序写IOPS=2745, BW=172MiB/s341.9664k顺序读IOPS=1501, BW=93.8MiB/s648.37

H730 mini(1G内存),总体利用率“74.72%”。

IOPS&BWclat(usec)4k随机写IOPS=1102, BW=4409KiB/s871.054k随机读IOPS=573, BW=2294KiB/s111525.2064k顺序写IOPS=2739, BW=171MiB/s341.7464k顺序读IOPS=2786, BW=174MiB/s341.09

从以上的结果可以发现,4k随机读和64k顺序写并没有明显的性能差异,但是:

4k随机写的性能,2G缓存的情况比1G缓存高约45%,延迟低约45%;64k顺序读的性能,1G缓存的情况比2G缓存高约84%,延迟低约90%。

关于这里的性能差异,还请存储方面的大神能帮忙解析一下。

测试SSD性能

一、测试目的

我们的测试还是以HDD为主,SSD(PCIe Intel P3600 1.6T)简单测试一下iodepth和numjobs,观察它与HDD在并发IO的情况下表现的趋势是HDD有什么差异,测试多了还挺心疼的。

二、测试内容

测试脚本:

[global] ioengine=libaio # 异步IO direct=1 # 排除OS的IO缓存机制的影响 size=5g # 每个fio进程/线程的最大读写 lockmem=1G # 锁定所使用的内存大小 runtime=30 # 根据上面的结论以后采用30值 directory=/mnt/ssd # 挂载的SSD,XFS格式 numjobs=1 # 同时进行的任务数 iodepth=1 # 队列深度 group_reporting # 多个job合并出报告 [4k_randwrite] stonewall # 隔离各测试任务 rw=randwrite bs=4k [4k_randread] stonewall rw=randread bs=4k [64k_write] stonewall rw=write bs=64k [64k_read] stonewall rw=read bs=64k

然后测试numjobs和iodepth的变化对结果的影响:

mkdir -p logs/ssd idx=0 for numjobs in 1 2 4; do for iodepth in 1 2 4 8 16 32; do sed -i "/^numjobs/c numjobs=${numjobs}" fio.conf && \ sed -i "/^iodepth/c iodepth=${iodepth}" fio.conf && \ fio fio.conf | tee logs/ssd/$(printf "%02d" ${idx})_n${numjobs}i${iodepth}.log && \ let idx++ && sleep 30s done done

最后,测试结果如下:

这个结果增加了一列numjobs和iodepth的乘积,并按照乘积进行了排序(HDD的时候是按numjobs进行排序的);而IOPS列被隐藏了,因为反正和BW是固定的比例。

三、测试结论

SSD对numjobs和iodepth的敏感程度似乎是一样的,并没有哪一个参数起主导作用的情况(而HDD的测试中numjobs对延迟等方面的影响更大)。如果说numjobs是批次数量,而iodepth是每个批次中的IO数量,SSD则完全不管IO操作是不是一批、是不是来自一个测试进程,只是机械地处理,所以跟总的吞吐量(即“乘积”)是有关系的。从HDD与SDD的不同表现可以推测,RAID卡的缓存机制对HDD是有影响的(SSD是PCIe直插,不经过RAID卡)。SSD的各种IO读写方式的性能高峰: 4k随机写:**乘积到达8**的时候BW到达最高,而延迟并不高,再大的量会略微提高延迟。4k随机读:乘积为64和128的时候BW差距已经不大(为了验证,再增加一项测试,单独为4k随机读开个小灶numjobs=8, iodepth=32,BW为1530,calt为630.55),所以可以认为乘积达到64是较优参数。64k顺序写:乘积2,出道即巅峰,乘积越高延迟越高。64k顺序读:这似乎是个特例,两个参数都为1的时候,估计比较“专心”,性能挺高(这不是性能抖动,两块SSD的两次测试都是相近的结果),总体来说,乘积为32是较优参数。 整个测试过程,SSD的磁盘利用率都很高,毕竟相比HDD来说,没有各种机械运动。总起来说,SSD(PCIe Intel P3600 1.6T)的最高性能:4k随机写1180MiB/s,4k随机读1450MiB/s,64k顺序写1550MiB/s,64k顺序读2650MiB/s。

对比一下HDD(单盘RAID0-with-1Gcache/read-ahead/write-back)的最高性能:4k随机写4+MiB/s,4k随机读2+MiB/s,64k顺序写170MiB/s,64k顺序读170MiB/s。留点面子,延迟就不拿出来了 T_T



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3