Update:
修改一个错误。
原来写的是:%util = ((IO/s * svctm) * 1000) * 100% = 92.9336%,发出来之后7D Group群里有人说,这个应该是%util = ((IO/s * svctm) / 1000) * 100% = 92.9336%,我一看,咦,还真写错了。
知错就改,还是好孩子,所以我改了。
今天周日,难得一个周日可以坐在这里发会呆。
但是看到7DGroup总群里,老郑发了一个IO的图。
还问了一句,为啥%util这么低呢?
看消息是上周五发的了,而当时,我在培训中,就随便不负责任地回了句,拿其他工具再验证一下。
但是今天没事干,于是较真的技术人都手贱的偏执劲就又来了。
拿上图的倒数第二条计算了一下(本来是用倒数第一条算的,结果被logo水印挡住了,担心看文章的人比我还较真,就换了倒数第二条算)。
%util = ((151 * 0.17 ) / 1000 ) * 100% = 2.567%
算到这里,真想揍老郑,这不是挺正常的低吗?我还以为低得不正常。
但是这个图能不能说明磁盘是有瓶颈的呢?
毕竟前面的计算浪费了自己的时间,总得让浪费的时间有价值。
都到这里了,那就再手贱一点,自己做个例子,正好也说明下IO到底怎么才算是有瓶颈的。
说这个之前,还是要说一下什么是一次IO时间长度。 简言之:
一次IO时间 = 磁盘旋转延时 + 寻道时间 + 数据传输时间(这是对传统的带磁头的硬盘说的)
一次IO时间 = 寻找map table时间 + 数据传输时间 (这是对SSD磁盘说的)
不过上面这个似乎和本文无关,有人说了:无关你说它干吗?....你猜。
示例是这样的:
fio --filename=fio.tmp --direct=1 --rw=randwrite --bs=4k --size=1G --numjobs=64 --runtime=100 --group_reporting --name=test-rand-write
开两个SSH窗口,一边用fio做随机写,一边开着iostat看IO状态。
现在来看看这个磁盘的IO是不是有瓶颈。
从%util来看,已经用到了92%以上。凭主观感觉,这是高得离谱呀。
但是从svctm来看,0.8ms的平均值似乎还是可以接受的。再加上await并没有特别高,只有0.8ms左右。
所以呢,await/svctm = 0.8ms / 0.8ms = 1。再看下avgqu-sz才0.97,队列不长。这不挺好的。
下面还是通过一些计算来说明(拿右边最后一组数据来算)。
IO/s = r/s + w/s = 1161.67
%util = ((IO/s * svctm) / 1000) * 100% = 92.9336%
也就是说,虽然%util很高,其实现在的io队列并不高,所以磁盘瓶颈是确切的,但是还不是特别离谱。
那为什么%util和算出来的不一致呢。
那得先svctm是个什么玩意?平均IO的时间,毫秒为单位。
这个值在sysstat中的说明中,提到了。
svctm
The average service time (in milliseconds) for I/O requests that were issued to the device. Warning! Do not trust this field any more. This field will be removed in a future sysstat version.
%util
Percentage of elapsed time during which I/O requests were issued to the device (bandwidth utilization for the device). Device saturation occurs when this value is close to 100% for devices serving requests serially. But for devices serving requests in parallel, such as RAID arrays and modern SSDs, this number does not reflect their performance limits.
svctm原来已经不可信了。
并且这里也提到了在raid和ssd磁盘中,%util不能做为磁盘瓶颈的标准了。(官方也真够有意思的,都不准了,还拿出来忽悠人。)
再来计算一下平均等待时间,假设fio发的io请求是同时的,numjobs=64,并发64个线程。
平均等待时间 = 0.8ms(svctm) * ( 1+...+ 1161.67 -1)/1161.67 约等于 = 464.67 ms
但是iostat给的结果是await为0.84ms,可见这IO完全不是同时发出的。差太多了。
这里说一下插曲:我设置的并发线程数是64,为啥不同时发出呢?
看了下cs,每个fio进程都有近100的上下文切换,当用64线程的时候,每一个进程倒是不算高,加一起就不算低了。磁盘瓶颈前面提到了,不算高得离谱,但是它也导致了CS的出现。以后再写文章说CS的事情。今天还是专注说IO瓶颈。
从上面的数据来看,要判断IO的瓶颈,看%util和svctm,也是不够,单个参数的值只能做为一个参考。
await作为等待时间可以依赖。
由于svctm值的不完全可信,导致之前判断磁盘瓶颈的方法(await/svctm)可能会是有问题的。但是这个比值的参数价值还是不小的。
所以判断磁盘瓶颈,在await/svctm的基础上,还要再加上avgqu-sz的值做为证据。
所以上面的fio例子,磁盘是有瓶颈的,但是并没有特别离谱。
下面来看一个离谱的例子:
看到这个图,顿时觉得上面的那个根本不是事。await高达800ms以上,队列高达100以上。但是看起来iops比刚才少了很多,在这个离谱的例子中,等的时间远远大于了平均处理时间,这磁盘瓶颈是毫无疑问的坐实了。
再回到一开始的那张图,虽说%util不高,但是await/svctm已经很大了,同时磁盘队列已经出现。所以确定磁盘是有瓶颈的。
性能分析在OS层面有很多事情要理解。相比较代码、应用服务器、数据库层面。OS可能更难理解。但是OS可以给出明确的方向。
写完又读了一遍,觉得写的不是不够细,但是不想再接着写下去了,以后再续吧。