以Little's Law角度解读iostat输出的avgqu-sz(平均队列长度)

Last update: 20181213

之前在博文性能分析中科特尔法则(Little’s Law)与其衍生法则的应用有介绍过Little’s law合它的简单证明过程,但此文中并没有给出相应的应用实例。 本文通过以Little’s law角度解读iostat命令输出的avgqu-sz指标。

查看平均队列长度

最简单的方法是通过命令 iostat -x 1 以每隔一秒一次输出队列长度,如下图所示。

红框所示的avgqu-sz就是平均队列长度了,这里直接引用博文 http://bean-li.github.io/dive-into-iostat/
中给出的计算方法。

我们换一种思路来考虑,即diskstats中time_in_queue的思路。
当第一个IO完成的时候,队列中250个IO,250个IO都等了4ms,即time_in_queue + = (2504) ,当第二个IO完成的时候,time_in_queue += (2494),当所有IO都完成的时候,time_in_queue = 4*(250+249+248….+1), …
根据time_in_queue/1000,殊途同归地获得了平均队列长度。

第一次读到这段解释时似懂非懂,后来想起来在证明Little’s Law的过程中曾使用面积的来替代队列中的总等待时间并除以观察时间得出平均队列长度。通过这个方法来理解iostat的计算队列长度会简单得多,而且有利于加深对Little’s Law的理解。

借用Little’s Law的证明思路

我们回顾下Little’s law的证明过程,

Little’s law中不太好理解的参数是队列中平均任务数,请参考上图中的绿色部分A(T)。A(T)为T观察时间范围内,已经入队到队列中的所有任务等待时间的总和,也可以理解为绿色部分的面积。当由n(t)导致的不规则绿色区域抹平成长方形时,设T为长方形的宽,队列中的平均任务数为高,则A(T) = T * 队列中平均任务数。设L(T) = A(T) / T,则L(T)等同于平均等待任务数(也称为平均队列长度)。

上面一段是博文”性能分析中科特尔法则(Little’s Law)与其衍生法则的应用”的片段。由于观察范围时间T可以由我们指定,那我们需要计算出绿色区域面积就可以得出平均队列长度。

那问题变成了我们怎么能获取队列中的所有任务的等待时间呢?
在Linux 内核(以4.4版本为例)中有如下代码,它在每次关键IO事件时会被调用。

其中time_in_queue就等同于上面所说的”入队到队列中的所有任务等待时间的总和”。
每当发生以下几个IO事件时会触发IO统计,也就是调用part_round_stats_single()。

  • 当有新的IO请求入队
  • 当IO请求被已有请求合并(Front merge or Back merge)时
  • 当完成某个IO请求时

在博文 http://bean-li.github.io/dive-into-iostat/中有提到Merge时不会做IO统计函数,但是在kernel 4.4中可以到由blk_queue_bio()函数根据情况分别会调用attempt_front_merge()或attempt_back_merge()。

每当发生关键IO事件;发起请求,完成请求,请求被合并时查看当前有几条正在执行的读请求IO或写请求IO,将此值乘以临近时间差就得出了系统当前处理IO时的总耗时。这与Little’ Law中通过面积来计算总耗时是一个道理,”绿色面积”中每当一个请求来的时候就上调一格,完成IO时就下调一格。在观察时间周期T内,以此方法来画出的绿色区域就是请求的总耗时时间。需要再次强调的关键概念是:

  • 系统同时可以有多个读请求
  • 系统同时可以有多个写请求
  • 读请求与写请求可以同时发生

2:内核函数part_in_flight()中返回的IO数目也是读和写请求的总和。

如何获取平均服务时间?

Linux的/proc/diskstat中目前(4.4版本)只提供了处理完成的IO请求数量与IO等待时间,并没有提供请求入队的IO请求数量。在”性能分析中科特尔法则(Little’s Law)与其衍生法则的应用”也提到过Utilization law,是指当资源使用率不超过100%时可认为抵达率与完成率是一致的,这也意味着当资源使用率未达到100%时可以通过完成率替代抵达率以计算服务平均处理时间。iostat中用的方法也是利用了这一点,但本质上是Utilization law在发挥作用。如果遇到资源使用率达到性能拐点处时就已经不是job flow balance状态了(出现排队)。以严谨起见,最好是能获取到真正的请求入队数量,这样可以套用Little’s law计算出真正的平均服务时间。目前想到的唯一方法是通过修改内核代码以获取入队请求次数。

W = L / λ

补充:

当谈到Disk IO的服务时间时注意区分两种情况:

  • IO队列服务时间 = 磁盘忙于IO请求的时间 + IO请求在队列中等待时间
  • 磁盘IO服务时间 = 磁盘忙于IO请求的时间

Little’s Law给出的平均服务时间是指IO队列服务时间,他是包括了队列中的等待时间。那实践中以哪个指标为主呢?我觉得是根据应用场景不同而不同,

  • 分析某个workload characterization 时会侧重看IO队列服务时间
  • 分析某个设备整体情况时会侧重看磁盘IO服务时间。基于Flash的存储设备出现严重的文件碎片化时此值会暴增。

参考