了解一个系统的性能通常是参考一些度量值(Metric),而如何计算出这些Metric就是我们要讨论的。Little Law(排队理论:利特儿法则)和Utilization Law是Performance Engineering(System Engineering的一部分)常用的法则,它们都是数学理论,因此可作为性能计算的理论依据。详细分析两个法则超出了我个人的知识范围,因此我将仅仅谈一下如何应用。
在这之前我有写过存储系统性能 - 带宽计算,其中就应用到了Little Law和Utilization Law,大家可以参考一下。
Little Law 是由Philip M.Morse在1954年提出,公式为L = λW,但当时并没有被证明,所以仅仅假设为正确,而一直被人们使用着,Philip希望读者能够提供这种关系所不适用的情况来推翻它。John Little在1961年证明了并没有一种情况不适用于Little Law,从而为Little Law的正确性提供了理论证明。
Little Law定义了(以超市为例):在一个稳定的系统中,长时间观察到的平均顾客数量L = 长时间观察到的有效顾客到达速率λ * 平均每个顾客在系统中花费的时间W,即L = λW。本法则适用于任何系统,甚至是一个系统中的子系统,比如一家银行的客户队列。唯一的要求就是系统必须是稳定的,非抢占式的。
为了更好的理解Little Law,请考虑一家仅有一个柜台的小型超市,柜台每次只能服务一位顾客,并且假设所有人都会买东西,这个系统的工作流程可以化简为:入店 -> 浏览 -> 结账 -> 离开,这是一个稳定的系统。如果【顾客进入超市的速率 > 顾客离开超市的速率】,即Arrival rate > Exit rate,那么系统就会开始不稳定,因为等待的客户队列会逐渐变得无限长。
- Little Law告诉我们:超市内的平均客户数量L = 客户到达速率λ * 客户在超时内的逗留时间W,即L = λW
- 假设客户达到速率为10人/小时,平均每个人在超市内逗留0.5小时,那么该超市在任何一个时间点的顾客数量 L= 10 * 0.5 = 5人
- 现假设顾客开始蜂拥,达到速率增长至20人/小时,如果顾客逗留时间不变依然为0.5小时,那么超市必须能够容纳 L=20*0.5 = 10人,否则都多出的5人需要在超市外等待;如果超市暂时无法扩容,即只能容纳5人,为了让多出的5人不需要在超市外等待,必须缩短顾客逗留时间W = 5/20 = 0.25小时。
总结来说,在流量增加的情况下,为了保证系统稳定运行(保持一个可接受的队列长度,从而保证可接受的响应时间),即超市在任意时间点都能保证能够服务5位顾客的能力,根据Little Law法则,有两种方案:
- 第一:扩大超市容量(建造更大的超市)
- 第二:减少顾客逗留时间(提高柜台效率,比如增加柜台数量,培训柜台人员)
====================================================
说了那么多都没提到性能,别急,如果我们把同样的例子应用到磁盘系统,即:
l 确保磁盘稳定运行所允许的最大请求数量 L
l I/O请求达到速率 λ
l 磁盘处理每一个I/O所花费的时间 W
因此,保证一块磁盘稳定运行所允许的最大I/O请求数量 L = I/O请求达到速率λ * 磁盘处理每一个I/O所花费的时间W,即L = λW;同理,对于一个I/O控制器,到达速率必须 < 服务速率,或者说服务时间必须 < 内部到达时间,否则I/O控制器的处理能力无法满足过量的I/O请求,必然会导致性能下降。
结合Utilization Law(不介绍了,直接应用,它可用于描述I/O控制器的利用率),公式为 U = λ * Rs
l U = I/O控制器的利用率
l Rs = 服务时间,即控制器处理一个I/O的平均时间,对于磁盘来说,服务时间 Rs = 寻道时间 + 旋转延迟 + 内部传输速率(数据从一个盘面上的单个磁道传输到Buffer的速率),所以通常是一个定值,由磁盘本身的物理特性决定。
l λ = 到达速率
Little Law + Utilization Law可以推导出如下公式(推导过程省略,直接用)
l 平均响应时间 R = Rs / (1-U)
l 平均队列长度 Nq = U^2 /(1-U)
有了如上这些公式,我们来考虑这样一个磁盘系统, λ = 100个/秒,Rs = 8ms,我们可以得到
l 磁盘利用率 U = Rs / Ra = 8/10 = 0.8或80%
l 响应时间R = Rs / (1-U) = 8/(1-0.8) = 40ms
l 平均队列长度Nq = U^2 / (1-U) = 0.8^2 / (1-0.8) = 3.2
l 一个请求在队列中的等待时间 = 【U * Rs】或【响应时间 – 服务时间】 = 40 – 8 = 32ms
若把控制器处理能力加倍,则服务时间和利用率都会减半,Rs = 4ms,U = 40%。此时,响应时间R可以大大降低;同理,如果处理能力减半,那么服务时间和利用率都会极大增加。这里有一个非常重要的概念,就是我们经常提到的,随着利用率增加到某一个点,如果继续上升,那么响应时间会呈指数形式增长,也就是说R和U并不是线性的关系,我们分析一下【响应时间R = Rs / (1-U)】来看看是为什么:
平均响应时间 R = Rs / (1-U),Rs是定值,可见,当U = 1时,也就是控制器饱和时,【响应时间R】趋近于无穷大,这是一个极限的概念, ,当U趋向于1时,又Rs是常量,所以R趋向于无穷大。因此,处于100%利用率的控制器就是瓶颈所在,它会迫使I/O序列化(I/O serialization),即每个I/O都必须在队列中等待它前面的I/O被处理完毕之后才能得到服务。一旦队列无限加大(一般buffer会有控制机制阻止队列的无限增长,比如Fiber Channel BB Credit,TCP Window,Ethernet PAUSE等等),响应时间会急剧上升。
通常我们都认为当利用率达到70%以后,未来的继续增长会使得性能以指数形式下降,而不是线性的。为什么是非线性的,大家可以尝试画一下 R= Rs/ (1-U) 的函数图像,在U逐渐趋向于1时,R趋向于无穷大,垂直渐近线是 x = 1。不过我不明白70%是如何计算出来的,可能是求U在 [0,1)范围内的导数通过比较斜率变化率来判断的?事实上,当U取0.9,0.99,0.999,....,0.9999999时,你会发现R = 10Rs, 100Rs, 1000Rs,....,10000000Rs,R以指数形式增长。而U取0.1,0.11,0.111时,R的增加就缓慢很多。随着U的取值增加,R的上升趋势也会以非线性的方式呈上升趋势。70%可能是通过数学方式计算得到,也可能只是一个比较得来的经验值,擅长数学的朋友可以补充说明一下。
更多文章请关注微信公众号:Troubleshooter