Linux下的一些I/O统计工具

From: http://wgzhao.com/2012/08/22/some-way-to-io-statistics-on-linux/

 Linux 系统管理员,统计各类 IO 是一项必不可少的工作。其统计工具中 iostat 显然又是最重要的一个统计手段。但是这里 iostat 不是本文的重点,因为这个工具的使用在网络上已经有大量的教程,可以供大家参考。这里主要是想介绍一些其他统计工具以来满足不同的需求。

iostat

iostat 的功能异常强大,输出项也特别多,比如下面这个例子:

1
2
3
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util  sda 0.00 0.50 173.50 73.50 3076.00 604.00 29.80 149.93 676.58 74.36 2098.15 4.05 100.00

其各项的含义分别是:

  • rrqm/s: 每秒进行 merge 的读操作数目.即 delta(rmerge)/s
  • wrqm/s: 每秒进行 merge 的写操作数目.即 delta(wmerge)/s
  • r/s: 每秒完成的读 I/O 设备次数.即 delta(rio)/s
  • w/s: 每秒完成的写 I/O 设备次数.即 delta(wio)/s
  • rsec/s: 每秒读扇区数.即 delta(rsect)/s
  • wsec/s: 每秒写扇区数.即 delta(wsect)/s
  • rkB/s: 每秒读 K 字节数.是 rsect/s 的一半,因为每扇区大小为 512 字节.(需要计算)
  • wkB/s: 每秒写 K 字节数.是 wsect/s 的一半.(需要计算)
  • avgrq-sz: 平均每次设备 I/O 操作的数据大小 (扇区).delta(rsect+wsect)/delta(rio+wio)
  • avgqu-sz: 平均 I/O 队列长度.即 delta(aveq)/s/1000 (因为 aveq 的单位为毫秒).
  • await: 平均每次设备 I/O 操作的等待时间 (毫秒).即 delta(ruse+wuse)/delta(rio+wio)
  • svctm: 平均每次设备 I/O 操作的服务时间 (毫秒).即 delta(use)/delta(rio+wio)
  • %util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的.即 delta(use)/s/1000 (因为 use 的单位为毫秒)

如果 %util 接近 100%,说明产生的 I/O 请求太多,I/O 系统已经满负荷,该磁盘可能存在瓶颈.

idle 小于 70% IO 压力就较大了,一般读取速度有较多的 wait.

同时可以结合vmstat查看查看 b 参数(等待资源的进程数)和 wa 参数(IO 等待所占用的 CPU 时间的百分比,高过 30%时 IO 压力高)

另外 await 的参数也要多和 svctm 来参考。差的过高就一定有 IO 的问题.

avgrq-sz 也是个做 IO 调优时需要注意的地方,这个就是直接每次操作的数据的大小,如果次数多,但数据拿的小的话,其实 IO 也会很小.如果数据拿的大,才 IO 的数据会高.也可以通过 avgqu-sz × ( r/s or w/s ) = rsec/s or wsec/s.也就是讲,读定速度是这个来决定的.

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 洪水.

有时间的话,我会单独写几个帖子来说说iostat

iodump

iodump 是一个统计每一个进程(线程)所消耗的磁盘 I/O 工具。这个一个 perl 脚本,其原理时打开有关 I/O 的内核记录消息开关,而后读取消息然后分析输出。简单使用步骤如下:

首先下载这个工具

wget http://aspersa.googlecode.com/svn/trunk/iodump

然后打开有关 I/O 内核消息的开关

echo 1 >/proc/sys/vm/block_dump

上述开关打开后,内核会记录下每一个 I/O 操作的消息。我们只需要定时获取并分析就好了,比如下面这样

while true; do sleep 1; dmesg -c ; done |perl iodump

等待一段时间,然后通过ctrl+c来结束上述脚本,你将获得下面类似的信息:

1
2
3
4
5
6
7
TASK PID TOTAL READ WRITE DIRTY DEVICES postgres 5799 1919 1919 0 0 sda7 jbd2/sda7-8 1572 35 0 35 0 sda7 jbd2/sda2-8 250 32 0 32 0 sda2 flush-8:0 2229 31 0 31 0 sda2, sda7 postgres 4308 2 0 2 0 sda7 bash 5804 1 0 1 0 sda2

上述输出的单位为块(block),每块的大小取决于创建文件系统时指定的块大小。比如我这个里的 sda7 的 block 大小是 1KB。

iotop

iotop 是一个 Python 编写的工具,有类似top工具的 UI,包括一些参数也和top类似。不过它对系统有一些要求,分别是:

  1. Python ≥ 2.5 or Python ≥ 2.4 with the ctypes module
  2. Kernel ≥ 2.6.20
  3. Kernel uses options:
    1. TASK_DELAY_ACCT
    2. CONFIG_TASKSTATS
    3. TASK_IO_ACCOUNTING
    4. CONFIG_VM_EVENT_COUNTERS

如果是基于 RPM 包的系统,可以直接下载编译好的二进制包(here)或者二进制源代码包(here)

如果是 Debian/Ubuntu 系统,直接使用

sudo apt-get install iotop

即可(不得不说,Debian 系统提供的软件真的是相当丰富呀),其他系统则可以通过下面的指令下载源代码,然后编译

git clone git://repo.or.cz/iotop.git

具体的使用方法可以参考 iotop(8)手册,下面是在我机器上的一个显示:

1
2
3
4
5
6
iotop -o -u wgzhao Total DISK READ: 2.15 M/s | Total DISK WRITE: 1601.15 K/s  TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND  5984 be/4 wgzhao 2.15 M/s 70.55 K/s 0.00 % 83.67 % postgres: wgzhao pgbench [local] UPDATE  4305 be/4 wgzhao 0.00 B/s 227.34 K/s 0.00 % 0.00 % postgres: writer process  4308 be/4 wgzhao 0.00 B/s 90.15 K/s 0.00 % 0.00 % postgres: stats collector process

iopp

iopp 是另外一个统计每一个进程 I/O 的工具,使用 C 语言编写,理论上应该比上述两个重狙效率都要高。安装方法很简单,首先通过下面的指令下载源代码:

git://github.com/markwkm/iopp.git

然后分别通过下面的指令编译安装

1
2
3
cmake CMakeLists.txt make make install DESTDIR=/usr

下面是一个使用例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
iopp -i -c 2  pid rchar wchar syscr syscw rbytes wbytes cwbytes command  2144 0 296 40 8 0 0 0 /usr/sbin/LCDd  2284 0 0 2 0 0 0 0 ha_logd: read process  2299 0 0 2 0 0 0 0 ha_logd: write process  2520 3 3 3 3 0 0 0 /usr/lib/virtualbox/vboxwebsrv  2599 2 2 2 2 0 0 0 /usr/lib/virtualbox/VBoxSVC  2675 0 0 1 0 0 0 0 runsvdir  3177 16 16 4 2 0 0 0 /usr/bin/gnome-shell  3192 16 16 4 2 0 0 0 nautilus  3305 180 340 100 60 0 0 0 /usr/lib/icedove/icedove-bin  3623 1393 1440 1 1 0 0 0 sshd: wgzhao@pts/0  4305 0 4603904 0 562 0 4603904 0 postgres: writer process  6257 2064384 1892352 252 215 3719168 139264 0 postgres: wgzhao pgbench [local] UPDATE

上述输出的各项含义是:

  • pid 进程 ID
  • rchar 将要从磁盘读取的字节数
  • wchar 已经写入或应该要写入磁盘的字节数
  • syscr 读 I/O 数
  • syscw 写 I/O 数
  • rbytes 真正从磁盘读取的字节数
  • wbytes 真正写入到磁盘的字节数
  • cwbytes 因为清空页面缓存而导致没有发生操作的字节数
  • command 执行的命令

其中rbytes,wbytes,cwbytes会因给出-k或者-m参数,而显示为rkb,wkb,cwkbrmb,wmb,cwmbcommand一列如果给出-c的参数则显示完整的命令名而不仅仅只是命令本身。这些参数的使用和top类似。

更具体的可以参考 iopp(8)手册。

dstat

dstat 号称各种资源统计工具,其目的是想替代vmstat,iostat,netstat,ifstat等各种单一统计工具,从而做到All in one。 dstat 用 Python 语言编写。

dstat 能够清晰显示每列的信息,特别是单位及大小很明确,不会在单位换算上犯迷糊和失误。最重要的是,因为它是基于模块化设计,因此我们可以很容易的写一个插件来收集我们需要的统计信息。

另外,dstat 的输出还可以导出为CSV格式文件,从而可以在电子表格工具里分方便的生成统计图形。

目前 dstat 的插件已经相当多了,这是我机器上目前的输出:

1
2
3
4
5
6
7
8
9
10
11
12
$ dstat --list internal:  aio, cpu, cpu24, disk, disk24, disk24old, epoch, fs, int, int24, io, ipc, load, lock, mem, net,  page, page24, proc, raw, socket, swap, swapold, sys, tcp, time, udp, unix, vm /usr/share/dstat:  battery, battery-remain, cpufreq, dbus, disk-tps, disk-util, dstat, dstat-cpu, dstat-ctxt,  dstat-mem, fan, freespace, gpfs, gpfs-ops, helloworld, innodb-buffer, innodb-io, innodb-ops, lustre,  memcache-hits, mysql-io, mysql-keys, mysql5-cmds, mysql5-io, mysql5-keys, net-packets, nfs3,  nfs3-ops, nfsd3, nfsd3-ops, ntp, postfix, power, proc-count, qmail, rpc, rpcd, sendmail, snooze,  squid, test, thermal, top-bio, top-bio-adv, top-childwait, top-cpu, top-cpu-adv, top-cputime,  top-cputime-avg, top-int, top-io, top-io-adv, top-latency, top-latency-avg, top-mem, top-oom, utmp,  vm-memctl, vmk-hba, vmk-int, vmk-nic, vz-cpu, vz-io, vz-ubc, wifi

下面给出几个使用的列子(实际输出是带彩色的,很容易识别)

dstat 的缺省输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
wgzhao-nb:~# dstat You did not select any stats, using -cdngy by default. ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai hiq siq| read writ| recv send| in out | int csw  2 1 87 10 0 0| 816k 385k| 0 0 | 0 0 |2279 7048  5 1 78 16 0 0|2600k 0 | 140B 940B| 0 0 |5952 13k  5 3 80 12 0 0|2896k 182k| 70B 358B| 0 0 |6074 14k  4 2 78 16 0 0|2724k 0 | 70B 374B| 0 0 |5703 15k  4 2 81 14 0 0|3008k 0 | 70B 358B| 0 0 |5924 13k  5 1 80 14 0 0|1976k 17k| 70B 358B| 0 0 |5819 13k  5 2 79 14 0 0|2056k 0 | 198B 374B| 0 0 |5618 13k  4 2 79 15 0 0|2416k 0 | 70B 358B| 0 0 |5866 15k  5 2 78 15 0 0|2528k 0 | 70B 358B| 0 0 |6356 14k  5 2 78 16 0 0|2288k 0 | 70B 358B| 0 0 |6515 15k  5 2 79 14 0 0|2656k 8192B| 70B 358B| 0 0 |6490 15k  3 2 81 13 0 0|2296k 0 | 70B 374B| 0 0 |5573 15k  4 3 76 17 0 1|2224k 0 | 70B 358B| 0 0 |5366 12k  5 1 81 13 0 0|2208k 0 | 508B 358B| 0 0 |5403 13k  4 2 79 15 0 0|2024k 182k| 70B 358B| 0 0 |5583 13k  5 2 79 15 0 0|2148k 17k| 186B 490B| 0 0 |5400 12k

指定需要显示的列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
wgzhao-nb:~# dstat -c --top-cpu -d --top-bio --top-latency Module dstat_top_latency failed to load. (Kernel has no scheduler statistics, use at least 2.6.12) ----total-cpu-usage---- -most-expensive- -dsk/total- ----most-expensive---- usr sys idl wai hiq siq| cpu process | read writ| block i/o process  2 1 87 10 0 0|gnome-shell 0.7| 826k 384k|postgres 692k 52k  4 2 79 16 0 0|postgres: wgz3.0|1744k 776k|postgres: w1744k 72k  5 3 78 15 0 0|postgres: wgz5.0|3120k 0 |postgres: w3064k 136k  6 2 73 19 0 0|postgres: wgz4.2|2608k 285k|postgres: w2608k 136k  4 2 77 17 0 0|postgres: wgz3.5|2112k 848k|postgres: w2112k 88k  3 2 71 25 0 0|postgres: wgz2.0| 944k 1049k|postgres: w 936k 48k  3 2 58 37 0 0|postgres: wgz2.0| 920k 2070k|postgres: w 928k 64k  3 2 62 34 0 0|postgres: wgz2.2|1496k 992k|postgres: w1608k 72k  3 2 56 38 0 0|postgres: wgz3.0|1840k 645k|postgres: w1856k 88k  3 2 78 17 0 0|postgres: wgz3.0|1420k 1200k|postgres: w1292k 80k  5 2 80 12 0 1|postgres: wgz4.2|2628k 0 |postgres: w2636k 112k  4 3 69 25 0 0|postgres: wgz3.8|2168k 576k|postgres: w2224k 104k

指定需要显示的列,并同时将结果导出到文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wgzhao-nb:~# dstat --disk --mem --proc --io --sys --filesystem --tcp --vm --output dstat.csv -dsk/total- ------memory-usage----- ---procs--- --io/total- ---system-- --filesystem- ----tcp-sockets---- -----virtual-memory----  read writ| used buff cach free|run blk new| read writ| int csw |files inodes|lis act syn tim clo|majpf minpf alloc free  844k 404k| 829M 19.4M 2920M 124M| 0 0.0 0.7|47.5 38.4 |2336 7185 | 4928 12286 | 11 3 0 0 2| 1 620 602 605 2128k 1526k| 828M 19.4M 2915M 130M| 0 2.0 0| 111 157 |4588 14k| 4928 12285 | 11 3 0 0 2| 0 1859 995 2278  920k 2151k| 826M 19.4M 2917M 129M| 0 2.0 0|52.0 237 |3091 7540 | 4928 12284 | 11 3 0 0 2| 0 4448 2330 2144 2124k 1003k| 826M 19.4M 2921M 126M|1.0 1.0 0| 135 106 |4705 14k| 4928 12284 | 11 3 0 0 2| 0 331 865 1 2344k 1024k| 826M 19.4M 2924M 122M|1.0 2.0 0| 121 118 |4074 13k| 4928 12284 | 11 3 0 0 2| 0 249 953 1 1572k 1624k| 827M 19.4M 2926M 120M|1.0 2.0 0|87.0 190 |3231 11k| 4928 12284 | 11 3 0 0 2| 0 98 530 1  916k 788k| 827M 19.4M 2928M 119M| 0 2.0 0|68.0 92.0 |3452 8709 | 4928 12284 | 11 3 0 0 2| 0 128 383 4 2452k 1665k| 826M 19.4M 2931M 116M|1.0 1.0 0| 132 197 |4779 14k| 4928 12284 | 11 3 0 0 2| 0 208 822 1 1552k 1328k| 827M 19.4M 2933M 114M| 0 2.0 0|97.0 156 |3762 9117 | 4928 12284 | 11 3 0 0 2| 0 133 473 1 1192k 2024k| 827M 19.4M 2934M 112M| 0 2.0 0|81.0 239 |4068 11k| 4928 12284 | 11 3 0 0 2| 0 135 414 2 2668k 584k| 827M 19.4M 2937M 109M| 0 2.0 0| 148 71.0 |4415 10k| 4928 12284 | 11 3 0 0 2| 0 174 870 4 1712k 960k| 827M 19.4M 2940M 106M| 0 2.0 0| 122 113 |4454 14k| 4928 12284 | 11 3 0 0 2| 0 182 616 2

更详细的用法,可以参考 dstat(1)手册

你可能感兴趣的:(Linux下的一些I/O统计工具)