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开始。

 
1
2
3
4
5
6
7
8
9
# cat /proc/diskstats
   8       0 sda 239219 1806 37281259 2513275 904326 88832 50268824 26816609 0 4753060 29329105
   8       1 sda1 338 0 53241 6959 154 0 5496 3724 0 6337 10683
   8       2 sda2 238695 1797 37226458 2504489 620322 88832 50263328 25266599 0 3297988 27770221
   8      16 sdb 1009117 481 1011773 127319 0 0 0 0 0 126604 126604
   8      17 sdb1 1008792 480 1010929 127078 0 0 0 0 0 126363 126363
253       0 dm-0 1005 0 8040 15137 30146 0 241168 2490230 0 30911 2505369
253       1 dm-1 192791 0 35500457 2376087 359162 0 44095600 22949466 0 2312433 25325563
253       2 dm-2 47132 0 1717329 183565 496207 0 5926560 7348763 0 2517753 7532688

/proc/diskstats有11个字段,以下内核文档解释了它们的含义https://www.kernel.org/doc/Documentation/iostats.txt,我重新表述了一下,注意除了字段#9之外都是累计值,从系统启动之后一直累加:

  1. (rd_ios)读操作的次数。
  2. (rd_merges)合并读操作的次数。如果两个读操作读取相邻的数据块时,可以被合并成一个,以提高效率。合并的操作通常是I/O scheduler(也叫elevator)负责的。
  3. (rd_sectors)读取的扇区数量。
  4. (rd_ticks)读操作消耗的时间(以毫秒为单位)。每个读操作从__make_request()开始计时,到end_that_request_last()为止,包括了在队列中等待的时间。
  5. (wr_ios)写操作的次数。
  6. (wr_merges)合并写操作的次数。
  7. (wr_sectors)写入的扇区数量。
  8. (wr_ticks)写操作消耗的时间(以毫秒为单位)。
  9. (in_flight)当前未完成的I/O数量。在I/O请求进入队列时该值加1,在I/O结束时该值减1。
    注意:是I/O请求进入队列时,而不是提交给硬盘设备时。
  10. (io_ticks)该设备用于处理I/O的自然时间(wall-clock time)。
    请注意io_ticks与rd_ticks(字段#4)和wr_ticks(字段#8)的区别,rd_ticks和wr_ticks是把每一个I/O所消耗的时间累加在一起,因为硬盘设备通常可以并行处理多个I/O,所以rd_ticks和wr_ticks往往会比自然时间大。而io_ticks表示该设备有I/O(即非空闲)的时间,不考虑I/O有多少,只考虑有没有。在实际计算时,字段#9(in_flight)不为零的时候io_ticks保持计时,字段#9(in_flight)为零的时候io_ticks停止计时。
  11. (time_in_queue)对字段#10(io_ticks)的加权值。字段#10(io_ticks)是自然时间,不考虑当前有几个I/O,而time_in_queue是用当前的I/O数量(即字段#9 in-flight)乘以自然时间。虽然该字段的名称是time_in_queue,但并不真的只是在队列中的时间,其中还包含了硬盘处理I/O的时间。iostat在计算avgqu-sz时会用到这个字段。

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的表现不一样?

可以看到其它硬盘的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毫秒不等,具体看产品手册;
对于机械硬盘,可以参考以下文档中的计算方法:
http://cseweb.ucsd.edu/classes/wi01/cse102/sol2.pdf大致来说一万转的机械硬盘是8.38毫秒,包括寻道时间、旋转延迟、传输时间。

在实践中,要根据应用场景来判断await是否正常,如果I/O模式很随机、I/O负载比较高,会导致磁头乱跑,寻道时间长,那么相应地await要估算得大一些;如果I/O模式是顺序读写,只有单一进程产生I/O负载,那么寻道时间和旋转延迟都可以忽略不计,主要考虑传输时间,相应地await就应该很小,甚至不到1毫秒。在以下实例中,await是7.50毫秒,似乎并不大,但考虑到这是一个dd测试,属于顺序读操作,而且只有单一任务在该硬盘上,这里的await应该不到1毫秒才算正常:

 
1
2
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大大加快了,如果磁盘阵列的写操作不在一两个毫秒以内就算慢的了;读操作则未必,不在缓存中的数据仍然需要读取物理硬盘,单个小数据块的读取速度跟单盘差不多。

容易被误读的IOSTAT的更多相关文章

  1. 解决document.getElementById("")在IE7中误读成name的bug

    <!DOCTYPE html>      <html lang="en">      <head>          <meta char ...

  2. 【英语】Bingo口语笔记(73) - 以tly,tely结尾的误读

  3. [PHP]误读支付宝接口可能引发的乌龙

    ------------------------------------------------------------------------------------ 之所以发现这个坑,源起项目中的 ...

  4. 辩证看待 iostat

    前言 经常做系统分析会接触到很多有用的工具,比如 iostat,它是用来分析磁盘性能.系统 I/O 的利器. 本文将重点介绍 iostat 命令的使用,并分析容易引起误解的几个指标. iostat i ...

  5. 深入理解iostat

    前言 iostat算是比较重要的查看块设备运行状态的工具,相信大多数使用Linux的同学都用过这个工具,或者听说过这个工具.但是对于这个工具,引起的误解也是最多的,大多数人对这个工具处于朦朦胧胧的状态 ...

  6. [转载]深入理解iostat

    深入理解iostat 前言 iostat算是比较重要的查看块设备运行状态的工具,相信大多数使用Linux的同学都用过这个工具,或者听说过这个工具.但是对于这个工具,引起的误解也是最多的,大多数人对这个 ...

  7. 利用BLKTRACE分析IO性能

    在Linux系统上,如果I/O发生性能问题,有没有办法进一步定位故障位置呢?iostat等最常用的工具肯定是指望不上的,[容易被误读的iostat]一文中解释过await表示单个I/O所需的平均时间, ...

  8. Linux常用性能工具功能、用法及原理(一)

    Linux性能观测工具按类别可分为系统级别和进程级别,系统级别对整个系统的性能做统计,而进程级别则具体到进程,为每个进程维护统计信息. 按实现原理分,可分为基于计数器和跟踪以及剖析.含义如下: 计数器 ...

  9. Linux 磁盘告警分析

    硬件配置 cat /etc/redhat-release && dmidecode -s system-product-name && cat /proc/cpuinf ...

随机推荐

  1. asp.net core系列 39 Web 应用Razor 介绍与详细示例

    一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...

  2. redis 系列10 字符串对象

    一. 字符串对象编码 Redis中字符串可以存储3种类型,分别是字节串(byte string).整数.浮点数.在上章节中讲到字符串对象的编码可以是int, raw,embstr. 如果一个字符串对象 ...

  3. Kafka数据迁移

    1.概述 Kafka的使用场景非常广泛,一些实时流数据业务场景,均依赖Kafka来做数据分流.而在分布式应用场景中,数据迁移是一个比较常见的问题.关于Kafka集群数据如何迁移,今天笔者将为大家详细介 ...

  4. centos6.7 配置外网端口映射

    目的: 为节省公司外网ip,现需要把部分没有外网ip的服务器做端口映射. 服务器节点: 118.192.66.66(外网服务器) em1 内网 em2 外网 192.168.32.124(内网服务器) ...

  5. linux 制作不用密碼可立即登入的 ssh 用戶

    机器环境: 192.167.33.48 clent 用户:server 192.167.33.47 server 用户:server 1.客户端 生成密钥 ssh-keygen 2. 查看密钥文件权限 ...

  6. 第6章 演示服务器和测试 - Identity Server 4 中文文档(v1.0.0)

    您可以使用您喜欢的客户端库尝试IdentityServer4.我们在demo.identityserver.io上有一个测试实例.在主页面上,您可以找到有关如何配置客户端以及如何调用API的说明. 此 ...

  7. frame buffer简单应用

    现在我们要在LCD上画一个点,我们无法直接对LCD屏进行操作.这时候就需要用到FrameBuffer,Linux可以FrameBuffer这个设备来供用户态进程实现直接写屏.首先我们先简单看一下lin ...

  8. [PHP] 频率限制类

    比如要实现 单个ip限制60秒1次单个关键字,比如手机号,限制60秒1次,3600秒10次 <?php class Sina_Mail_WebAntispam { const PREFIX_WH ...

  9. Java开发笔记(九)赋值运算符及其演化

    前面的加减乘除四则运算,计算结果通过等号输出给指定变量,注意此时代码把变量放到等号左边.而在算术课本里,加法运算的完整写法类似于“1+1=2”这样,运算结果应该跟在等号右边.不过代数课本里的方程式存在 ...

  10. 当input框输入到限定长度时,自动focus下一个input框

     需求背景 需要输入一串15位的数字,但是要分为3个输入框,每个输入框限定长度5位,当删除当前输入框的内容时,focus到上一个输入框: 实现方法 var field = $('.phone-fiel ...