Linux性能分析工具(vmstat,iostat,sar)

Linux在具有高稳定性、可靠性的同时,具有很好的可伸缩性和扩展性,能够针对不同的应用和硬件环境调整,优化出满足当前应用需要的最佳性能。因此企业在维护Linux系统、进行系统调优时,了解系统性能分析工具是至关重要的。

  在Linux下有很多系统性能分析工具,比较常见的有top、free、ps、time、timex、uptime等。下文将介绍几个较为重要的性能分析工具vmstat、iostat和sar及其使用。

1.用vmstat监视内存使用情况

  vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存、进程、CPU活动进行监视。它是对系统的整体情况进行统计,不足之处是无法对某个进程进行深入分析。

  vmstat的语法如下:

程序代码
vmstat [-V] [-n] [delay [count]]



  其中,-V表示打印出版本信息;-n表示在周期性循环输出时,输出的头部信息仅显示一次;delay是两次输出之间的延迟时间;count是指按照这个时间间隔统计的次数。对于vmstat输出各字段的含义,可运行man vmstat查看。

ProCS

  r: 等待运行的进程数 b: 处在非中断睡眠状态的进程数 w: 被交换出去的可运行的进程数。此数由 Linux 计算得出,但 linux 并不耗尽交换空间

  Memory

  swpd: 虚拟内存使用情况,单位:KB
  free: 空闲的内存,单位KB
  buff: 被用来做为缓存的内存数,单位:KB
  Swap
  si: 从磁盘交换到内存的交换页数量,单位:KB/秒
  so: 从内存交换到磁盘的交换页数量,单位:KB/秒
  IO
  bi: 发送到块设备的块数,单位:块/秒
  bo: 从块设备接收到的块数,单位:块/秒
  System
  in: 每秒的中断数,包括时钟中断
  cs: 每秒的环境(上下文)切换次数
  CPU
  按 CPU 的总使用百分比来显示
  us: CPU 使用时间
  sy: CPU 系统使用时间
  id: 闲置时间
  准测
  r<5,b≈0,

   如果fre对于page列,re,pi,po,cy维持于比较稳定的状态,PI率不超过5,如果有pagin发生,那么关联页面必须先进行 pageout在内存相对紧张的环境下pagein会强制对不同的页面进行steal操作。如果系统正在读一个大批的永久页面,你也许可以看到po和pi 列会出现不一致的增长,这种情景并不一定表明系统负载过重,但是有必要对应用程序的数据访问模式进行见检查。在稳定的情况下,扫描率和重置率几乎相等,在 多个进程处理使用不同的页面的情况下,页面会更加不稳定和杂乱,这时扫描率可能会比重置率高出。

  faults列,in,sy,cs会不断跳跃,这里没有明确的限制,唯一的就是这些值最少大于100 cpu列,us,sys,id和wa也是不确定的,最理想的状态是使cpu处于100%工作状态,单这只适合单用户的情况下。

  如果在多用户环境中us+sys》80,进程就会在运行队列中花费等待时间,响应时间和吞吐量就会下降。wa>40表明磁盘io没有也许存在不合理的平衡,或者对磁盘操作比较频繁,vmstat各项:

procs: r-->在运行队列中等待的进程数 b-->在等待io的进程数 w-->可以进入运行队列但被替换的进程 memoy swap-->现时可用的交换内存(k表示) free-->空闲的内存(k表示) pages re--》回收的页面 mf--》非严重错误的页面 pi--》进入页面数(k表示) po--》出页面数(k表示) fr--》空余的页面数(k表示) de--》提前读入的页面中的未命中数 sr--》通过时钟算法扫描的页面 disk 显示每秒的磁盘操作。 s表示scsi盘,0表示盘号 fault 显示每秒的中断数 in--》设备中断 sy--》系统中断 cy--》cpu交换 cpu 表示cpu的使用状态 cs--》用户进程使用的时间 sy--》系统进程使用的时间 id--》cpu空闲的时间

  如果 r经常大于 4 ,且id经常少于40,表示cpu的负荷很重。

  如果pi,po 长期不等于0,表示内存不足。

  如果disk 经常不等于0, 且在 b中的队列 大于3, 表示 io性能不好。


2. 用iostat监视I/O子系统情况

   iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视。它的特点是汇报磁盘活动统计情况,同时也会汇报出 CPU使用情况。同vmstat一样,iostat也有一个弱点,就是它不能对某个进程进行深入分析,仅对系统的整体情况进行分析。

  iostat的语法如下:

程序代码
iostat [ -c | -d ] [ -k ] [ -t ] [ -V ] [ -x [ device ] ] [ interval [ count ] ]


   其中,-c为汇报CPU的使用情况;-d为汇报磁盘的使用情况;-k表示每秒按kilobytes字节显示数据;-t为打印汇报的时间;-v表示打印出 版本信息和用法;-x device指定要统计的设备名称,默认为所有的设备;interval指每次统计间隔的时间;count指按照这个时间间隔统计的次数。

  iostat一般的输出格式如下:
程序代码

Linux 2.4.18-18smp (builder.linux.com) 2003年03月07日

avg-cpu: %user %nice %sys %idle
4.81 0.01 1.03 94.15

Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
dev3-0 30.31 1117.68 846.52 16104536 12197374
dev3-1 7.06 229.61 40.40 3308486 582080

-------------------------------------------------------------------------------

iostat在内核2.4和内核2.6中数据来源不太一样,所以我们分别就这两中系统介绍iostat的输出。   
1. 内核2.4 iostat输出解析
对于kernel 2.4, iostat 的数据的主要来源是 /proc/partitions。
1.1  /proc/partition
先看看 /proc/partitions 中有些什么。
# cat /proc/partitions

major    minor    #blocks    name    rio      rmerge    rsect    ruse
3        0       19535040    hda    12524     31127     344371   344360
wio      wmerge   wsect      wuse    running  use       aveq
12941    25534    308434     1097290  -1      15800720   28214662

下面是每项数据的说明:
major:  主设备号。
minor:  次设备号。
#blocks: 设备总块数 (1024 bytes/block)。
name:    设备名称。如 hda7。
rio:     完成的读 I/O 设备总次数。指真正向 I/O 设备发起并完成的读操作数目,
      也就是那些放到 I/O 队列中的读请求。注意很多进程发起的读操作
      (read())很可能会和其他的操作进行 merge,不一定每个 read() 调用
      都引起一个 I/O 请求。
rmerge:  进行了 merge 的读操作数目。
rsect:   读扇区总数 (512 bytes/sector)
ruse:    从进入读队列到读操作完成的时间累积 (毫秒)。上面的例子显示从开机
         开始,读 hda7 操作共用了约340秒。
wio:     完成的写 I/O 设备总次数。
wmerge:  进行了 merge 的写操作数目。
wsect:   写扇区总数
wuse:    从进入写队列到写操作完成的时间累积 (毫秒)
running: 已进入 I/O 请求队列,等待进行设备操作的请求总数。上面的例子显
       示 磁盘上请求队列长度为 0。
use:     扣除重叠等待时间的净等待时间 (毫秒)。一般比 (ruse+wuse) 要小。比
      如5 个读请求同时等待了 1 毫秒,那么 ruse值为5ms, 而 use值为
         1ms。use 也可以理解为I/O队列处于不为空状态的总时间。hda7 的I/O
         队列非空时间为 509 秒,约合8分半钟。   
aveq:    在队列中总的等待时间累积 (毫秒) (约等于ruse+wuse)


1.2  iostat 结果解析
# iostat  -x
Linux 2.4.21-9.30AX (localhost)        

avg-cpu:  %user   %nice    %sys   %idle
           3.85    0.00    0.95   95.20

Device:     rrqm/s     wrqm/s     r/s      w/s     rsec/s    wsec/s   
/dev/hda    1.70        1.70      0.82     0.82    19.88     20.22
rkB/s       wkB/s      avgrq-sz  avgqu-sz  await   svctm      %util
9.94        10.11       24.50    11.83     57.81   610.76     99.96
每项数据的含义如下,
rrqm/s:    每秒进行 merge 的读操作数目。即 rmerge/s
wrqm/s:    每秒进行 merge 的写操作数目。即 wmerge/s
r/s:       每秒完成的读 I/O 设备次数。即 rio/s
w/s:       每秒完成的写 I/O 设备次数。即 wio/s
rsec/s:    每秒读扇区数。即 rsect/s
wsec/s:    每秒写扇区数。即 wsect/s
rkB/s:     每秒读K字节数。是 rsect/s 的一半,因为每扇区大小为512字节。
wkB/s:     每秒写K字节数。是 wsect/s 的一半。
avgrq-sz:  平均每次设备I/O操作的数据大小 (扇区)。即 (rsect+wsect)/(rio+wio)
avgqu-sz:  平均I/O队列长度。即 aveq/1000 (因为aveq的单位为毫秒)。
await:     平均每次设备I/O操作的等待时间 (毫秒)。即 (ruse+wuse)/(rio+wio)
svctm:     平均每次设备I/O操作的服务时间 (毫秒)。即 use/(rio+wio)
%util:    一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间
I/O队列是非空的,即use/1000 (因为use的单位为毫秒),
如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。

    svctm 一般要小于 await (因为同时等待的请求的等待时间被重复计算了),
svctm 的大小一般和磁盘性能有关,CPU/内存的负荷也会对其有影响,请求过多
也会间接导致 svctm 的增加。
await 的大小一般取决于服务时间(svctm) 以及 I/O 队列的长度和 I/O 请求的发出模式。如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;如果 await 远大于 svctm,说明 I/O 队列太长,应用得到的响应时间变慢,如果响应时间超过了用户可以容许的范围,这时可以考虑更换更快的磁盘,调整内核 elevator 算法,优化应用,或者升级 CPU。
   队列长度(avgqu-sz)也可作为衡量系统 I/O 负荷的指标,但由于 avgqu-sz 是
按照单位时间的平均值,所以不能反映瞬间的 I/O 洪水。

1.3  一个例子

# iostat -x 1
avg-cpu:  %user   %nice    %sys   %idle
          16.24    0.00    4.31   79.44
Device:    rrqm/s     wrqm/s       r/s        w/s     rsec/s     wsec/s  
/dev/cciss 0.00       44.90        1.02       27.55    8.16       579.59
rkB/s      wkB/s      avgrq-sz     avgqu-sz   await   svctm      %util
4.08       289.80     20.57        22.35      78.21    5.00       14.29           
   上面的 iostat 输出表明秒有 28.57 次设备 I/O 操作: io/s = r/s +w/s = 1.02+27.55 = 28.57 (次/秒) 其中写操作占了主体 (w:r = 27:1)。

   平均每次设备 I/O 操作只需要 5ms 就可以完成,但每个 I/O 请求却需要等上
78ms,为什么? 因为发出的 I/O 请求太多 (每秒钟约 29 个),假设这些请求是
同时发出的,那么平均等待时间可以这样计算:
    平均等待时间 = 单个 I/O 服务时间 * ( 1 + 2 + ... + 请求总数-1) / 请求总数.
    应用到上面的例子: 平均等待时间 = 5ms * (1+2+...+28)/29 = 70ms,和
iostat 给出的 78ms 的平均等待时间很接近。这反过来表明 I/O 是同时发起的。

    每秒发出的 I/O 请求很多 (约 29 个),平均队列却不长 (只有 2 个 左右),
这表明这 29 个请求的到来并不均匀,大部分时间 I/O 是空闲的。

    一秒中有 14.29% 的时间 I/O 队列中是有请求的,也就是说,85.71% 的时间里
I/O 系统无事可做,所有 29 个 I/O 请求都在142毫秒之内处理掉了。

   (ruse+wuse)/io = await = 78.21 => (ruse+wuse)/s =78.21 * (io)/s = 78.21*28.57 = 2232.8,表明每秒内的I/O请求总共需要等待2232.8ms。所以平均队列长度应为 2232.8ms/1000ms = 2.23,而 iostat 给出的平均队列长度 (avgqu-sz) 却为 22.35,为什么?! 因为 iostat 中有 bug,avgqu-sz 值应为 2.23,而不是 22.35。

    iostat.c 中是这样计算avgqu-sz的:
        ((double) current.aveq) / itv
    aveq 的单位是毫秒,而 itv 是两次采样之间的间隔,单位是 jiffies。必须换
算成同样单位才能相除,所以正确的算法是:
    (((double) current.aveq)/1000) / (itv /HZ)
这样,上面 iostat 中输出的 avgqu-sz 值应为 2.23,而不是 22.3。





2. 内核2.6 iostat输出解析
在2.6中,数据来源主要是/proc/diskstats和/sys/block/sd*/stat这两个文件,下面分别介绍这两个文件中各项数据的含义。
2.1 /proc/diskstats
cat /proc/diskstats | grep sda

8    0  sda  470792  145771  62327442  3897542  11350  2076 
276664 326820 0 2416014 4224415
  
8    1 sda1 7386 252826 7444 65336
    8    2 sda2 609103 62074384 4220 197216
   
其信息与2.4中/proc/partition类似,但没有标题栏,上面的信息中首先是磁盘的信息,后面接着的是磁盘分区的信息。

我们首先看磁盘的信息,总共有14列信息(标记为红色的部分)。
Field 1 : 磁盘主设备号(major)
Field 2 : 磁盘次设备号(minor)
Field 3 : 磁盘的设备名(name)
Field 4 : 读请求总数(rio)
Field 5 : 合并的读请求总数(rmerge)
Field 6 : 读扇区总数(rsect)
Field 7 :  读数据花费的时间,单位是ms.(从__make_request到 end_that_request_last)(ruse)
Field 8 :  写请求总数(wio)
Field 9 :  合并的写请求总数(wmerge)
Field 10 : 写扇区总数(wsect)
Field 11 : 写数据花费的时间,单位是ms. (从__make_request到 end_that_request_last)(wuse)
Field 12 : 现在正在进行的I/O数(running),等于I/O队列中请求数
Field 13 : 系统真正花费在I/O上的时间,除去重复等待时间(aveq)
Field 14 : 系统在I/O上花费的时间(use)。

我们再看分区信息(标记为紫色的部分)
这部分信息比较简单,除了前面的主次设备号和设备名外,后面依次分别是:读请求数,读扇区数,写请求数,写扇区数。




2.2 /sys/block/sd*/stat
Cat /sys/block/sda/stat

470792   145771 62327442  3897542    11359     2078   276752   327045        0  2416053  4224640

这些数据其实与/proc/diskstats中除设备号与设备名外的其它数据是一一对应关系,只是统计的方法略有差别而已。

------------------------------------------------------------------------------

对于输出中各字段的含义,iostat的帮助中有详细的说明。
使用sar进行综合分析

  表1 sar参数说明

  选项 功能

  -A 汇总所有的报告

  -a 报告文件读写使用情况

  -B 报告附加的缓存的使用情况

  -b 报告缓存的使用情况

  -c 报告系统调用的使用情况

  -d 报告磁盘的使用情况

  -g 报告串口的使用情况

  -h 报告关于buffer使用的统计数据

  -m 报告IPC消息队列和信号量的使用情况

  -n 报告命名cache的使用情况

  -p 报告调页活动的使用情况

  -q 报告运行队列和交换队列的平均长度

  -R 报告进程的活动情况

  -r 报告没有使用的内存页面和硬盘块

  -u 报告CPU的利用率

  -v 报告进程、i节点、文件和锁表状态

  -w 报告系统交换活动状况

  -y 报告TTY设备活动状况



   sar是System Activity Reporter(系统活动情况报告)的缩写。顾名思义,sar工具将对系统当前的状态进行取样,然后通过计算数据和比例来表达系统的当前运行状态。它的 特点是可以连续对系统取样,获得大量的取样数据;取样数据和分析的结果都可以存入文件,所需的负载很小。sar是目前Linux上最为全面的系统性能分析 工具之一,可以从14个大方面对系统的活动进行报告,包括文件的读写情况、系统调用的使用情况、串口、CPU效率、内存使用状况、进程活动及IPC有关的 活动等,使用也是较为复杂。

  sar的语法如下:
程序代码

sar [-option] [-o file] t [n]


  它的含义是每隔t秒取样一次,共取样n次。其中-o file表示取样结果将以二进制形式存入文件file中。

  另一种语法如下: 程序代码
sar [-option] [-s time] [-e time] [-i sec] [-f file]



   含义是表示从file文件中取出数据,如果没有指定-f file,则从标准数据文件/var/adm/sa/sadd取数据,其中dd表示当前天。另外,-s time表示起始时间;-e time表示停止时间;-i sec表示取样的时间间隔,如果不指定则表示取文件中所有的数据。对于具体的选项参见表1。

  一般它与-q和-u联合使用,以便对每个CPU的使用情况进行分析,比如运行如下命令:

程序代码
sar -q -u 5 1

将输出如下:
程序代码
Linux 2.4.18-18smp (builder.linux.com)  2003年03月07日

09时46分16? CPU %user %nice %system %idle
09时46分21? all 0.20 0.00 0.00 99.80

09时46分16? runq-sz plist-sz ldavg-1 ldavg-5
09时46分21? 0 91 0.00 0.00

Average: CPU %user %nice %system %idle
Average: all 0.20 0.00 0.00 99.80

Average: runq-sz plist-sz ldavg-1 ldavg-5
Average: 0 91 0.00 0.00

猜你喜欢

转载自hooray520.iteye.com/blog/1169554