欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

容易被误读的iostat

程序员文章站 2022-09-04 15:45:41
iostat(1)是在Linux系统上查看I/O性能最基本的工具,然而对于那些熟悉其它UNIX系统的人来说它是很容易被误读的。比如在HP-UX上 avserv(相当于Linux上的 svctm)是最重要的I/O指标,反映了硬盘设备的性能,它是指I/O请求从SCSI层发出、到I/O完成之后返回SCSI ......

iostat(1)是在linux系统上查看i/o性能最基本的工具,然而对于那些熟悉其它unix系统的人来说它是很容易被误读的。比如在hp-ux上 avserv(相当于linux上的 svctm)是最重要的i/o指标,反映了硬盘设备的性能,它是指i/o请求从scsi层发出、到i/o完成之后返回scsi层所消耗的时间,不包括在scsi队列中的等待时间,所以avserv体现了硬盘设备处理i/o的速度,又被称为disk service time,如果avserv很大,那么肯定是硬件出问题了。然而linux上svctm的含义截然不同,事实上在iostat(1)和sar(1)的man page上都说了不要相信svctm,该指标将被废弃:
“warning! do not trust this field any more. this field will be removed in a future sysstat version.”
在linux上,每个i/o的平均耗时是用await表示的,但它不能反映硬盘设备的性能,因为await不仅包括硬盘设备处理i/o的时间,还包括了在队列中等待的时间。i/o请求在队列中的时候尚未发送给硬盘设备,即队列中的等待时间不是硬盘设备消耗的,所以说await体现不了硬盘设备的速度,内核的问题比如i/o调度器什么的也有可能导致await变大。那么有没有哪个指标可以衡量硬盘设备的性能呢?非常遗憾的是,iostat(1)和sar(1)都没有,这是因为它们所依赖的/proc/diskstats不提供这项数据。要真正理解iostat的输出结果,应该从理解/proc/diskstats开始。

《初探diskstats》

iostat(1)是以/proc/diskstats为基础计算出来的,因为/proc/diskstats并未把队列等待时间和硬盘处理时间分开,所以凡是以它为基础的工具都不可能分别提供disk service time以及与queue有关的值。
注:下面的公式中“δ”表示两次取样之间的差值,“δt”表示采样周期。
• tps:每秒i/o次数=[(δrd_ios+δwr_ios)/δt]• r/s:每秒读操作的次数=[δrd_ios/δt]
• w/s:每秒写操作的次数=[δwr_ios/δt]

• rkb/s:每秒读取的千字节数=[δrd_sectors/δt]*[512/1024]
• wkb/s:每秒写入的千字节数=[δwr_sectors/δt]*[512/1024]
• rrqm/s:每秒合并读操作的次数=[δrd_merges/δt]
• wrqm/s:每秒合并写操作的次数=[δwr_merges/δt]
• avgrq-sz:每个i/o的平均扇区数=[δrd_sectors+δwr_sectors]/[δrd_ios+δwr_ios]
• avgqu-sz:平均未完成的i/o请求数量=[δtime_in_queue/δt]
(手册上说是队列里的平均i/o请求数量,更恰当的理解应该是平均未完成的i/o请求数量。)
• await:每个i/o平均所需的时间=[δrd_ticks+δwr_ticks]/[δrd_ios+δwr_ios]
(不仅包括硬盘设备处理i/o的时间,还包括了在kernel队列中等待的时间。)
• r_await:每个读操作平均所需的时间=[δrd_ticks/δrd_ios]
不仅包括硬盘设备读操作的时间,还包括了在kernel队列中等待的时间。
• w_await:每个写操作平均所需的时间=[δwr_ticks/δwr_ios]
不仅包括硬盘设备写操作的时间,还包括了在kernel队列中等待的时间。

• %util:该硬盘设备的繁忙比率=[δio_ticks/δt]
表示该设备有i/o(即非空闲)的时间比率,不考虑i/o有多少,只考虑有没有。
• svctm:已被废弃的指标,没什么意义,svctm=[util/tput]
对iostat(1)的恰当解读有助于正确地分析问题,我们结合实际案例进一步讨论。

关于rrqm/s和wrqm/s
前面讲过,如果两个i/o操作发生在相邻的数据块时,它们可以被合并成一个,以提高效率,合并的操作通常是i/o scheduler(也叫elevator)负责的。
以下案例对许多硬盘设备执行同样的压力测试,结果惟有sdb比其它硬盘都更快一些,可是硬盘型号都一样,为什么sdb的表现不一样?

容易被误读的iostat

 

可以看到其它硬盘的rrqm/s都为0,而sdb不是,就是说发生了i/o合并,所以效率更高,r/s和rmb/s都更高,我们知道i/o合并是内核的i/o scheduler(elevator)负责的,于是检查了sdb的/sys/block/sdb/queue/scheduler,发现它与别的硬盘用了不同的i/o scheduler,所以表现也不一样。

%util与硬盘设备饱和度
%util表示该设备有i/o(即非空闲)的时间比率,不考虑i/o有多少,只考虑有没有。由于现代硬盘设备都有并行处理多个i/o请求的能力,所以%util即使达到100%也不意味着设备饱和了。举个简化的例子:某硬盘处理单个i/o需要0.1秒,有能力同时处理10个i/o请求,那么当10个i/o请求依次顺序提交的时候,需要1秒才能全部完成,在1秒的采样周期里%util达到100%;而如果10个i/o请求一次性提交的话,0.1秒就全部完成,在1秒的采样周期里%util只有10%。可见,即使%util高达100%,硬盘也仍然有可能还有余力处理更多的i/o请求,即没有达到饱和状态。那么iostat(1)有没有哪个指标可以衡量硬盘设备的饱和程度呢?很遗憾,没有。

await多大才算有问题
await是单个i/o所消耗的时间,包括硬盘设备处理i/o的时间和i/o请求在kernel队列中等待的时间,正常情况下队列等待时间可以忽略不计,姑且把await当作衡量硬盘速度的指标吧,那么多大算是正常呢?
对于ssd,从0.0x毫秒到1.x毫秒不等,具体看产品手册;
对于机械硬盘,可以参考以下文档中的计算方法:
大致来说一万转的机械硬盘是8.38毫秒,包括寻道时间、旋转延迟、传输时间。
在实践中,要根据应用场景来判断await是否正常,如果i/o模式很随机、i/o负载比较高,会导致磁头乱跑,寻道时间长,那么相应地await要估算得大一些;如果i/o模式是顺序读写,只有单一进程产生i/o负载,那么寻道时间和旋转延迟都可以忽略不计,主要考虑传输时间,相应地await就应该很小,甚至不到1毫秒。在以下实例中,await是7.50毫秒,似乎并不大,但考虑到这是一个dd测试,属于顺序读操作,而且只有单一任务在该硬盘上,这里的await应该不到1毫秒才算正常:

 

device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sdg               0.00     0.00  133.00    0.00  2128.00     0.00    16.00     1.00    7.50   7.49  99.60

  

对磁盘阵列来说,因为有硬件缓存,写操作不等落盘就算完成,所以写操作的service time大大加快了,如果磁盘阵列的写操作不在一两个毫秒以内就算慢的了;读操作则未必,不在缓存中的数据仍然需要读取物理硬盘,单个小数据块的读取速度跟单盘差不多。