磁盘IO满负荷性能分析(一) | |||
|
$iostat -x 1 Linux 2.6.33-fukai (fukai-laptop) _i686_ (2 CPU) avg-cpu: %user %nice %system %iowait %steal %idle
5.47 0.50 8.96 48.26 0.00 36.82
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sda 6.00 273.00 99.00 7.00 2240.00 2240.00 42.26 1.12 10.57 7.96 84.40
sdb 0.00 4.00 0.00 350.00 0.00 2068.00 5.91 0.55 1.58 0.54 18.80
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 的问题。
avgqu-sz 也是个做 IO 调优时需要注意的地方,这个就是直接每次操作的数据的大小,如果次数多,但数据拿的小的话,其实 IO 也会很小.如果数据拿的大,才IO 的数据会高。也可以通过 avgqu-sz × ( r/s or w/s ) = rsec/s or wsec/s.也就是讲,读定速度是这个来决定的。
下面是别人写的这个参数输出的分析
# 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 rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
/dev/cciss/c0d0 0.00 44.90 1.02 27.55 8.16 579.59 4.08 289.80 20.57 22.35 78.21 5.00 14.29
上面的 iostat 输出表明秒有 28.57 次设备 I/O 操作: 总IO(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毫秒之内处理掉了。
delta(ruse+wuse)/delta(io) = await = 78.21 => delta(ruse+wuse)/s =78.21 * delta(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。
IO系统性能之三:在Linux中监视IO性能
dd命令
dd其实是工作于比较低层的一个数据拷贝和转换的*nix平台的工具,但是因为dd命令支持*nix平台的一些特殊设备,因此我们可以利用dd命令的这个特性来简单的测试磁盘的性能。
先说一下两个相关的特殊设备
-
/dev/null
- 空设备,通常用作输出设备,这个是*nix系统上面的黑洞,所有送到这个空设备上的内容都会凭空消失。 /dev/zero
- 空字符,通常用作输入,从/dev/zero中读取时,它能源源不断的提供空字符(ASCII NUL, 0×00)出来,要多少有多少。
于是就有了下面的用法:
- 测试磁盘的写入
这个命令时往磁盘的文件/tmp/foo中写入一个4G大小的文件,当然文件的内容全部是空字符了,同时用/usr/bin/time来对命令的执行进行计时,命令中的bs指的是写入文件时的块大小,其实就相当于Oracle中的block大小了,count是写入的块数。采取这种方法来写入数据时只是测试的连续读磁盘的性能,而不是随机读的性能,不能采取这种方法检查一个机器的IOPS的,只能检查磁盘的吞吐率。
- 测试磁盘的读取
上面的命令是从/tmp/foo文件中读取数据,然后扔掉,这里bs用的是读取时块的大小。和上面写入的命令一样,这样测试的仅仅是最大的读取性能,而不是随机IO的性能。
- 还能读写同时测试
在上面的命令中都用到了time命令对操作进行计时,这样才能正确的进行判断。要记住的一点是dd命令只能够提供一个大概的测试,通过这个简单的命令可以对磁盘系统的最大性能有一个大概的了解,要了解更详细的信息还要通过其他方法来查看。
topiostat命令
top理解iostat的各项输出
在Linux中,我们执行一个iostat -x命令,我们能看到如下的输出
Linux 2.4.21-50a6smp (linux) 11/03/2009
avg-cpu: %user %nice %sys %iowait %idle
0.42 0.00 0.26 0.47 98.86
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
hdc 0.01 0.00 0.00 0.00 0.07 0.00 0.03 0.00 24.48 0.00 4.90 4.57 0.00
hda 0.89 8.54 0.74 4.49 12.60 104.22 6.30 52.11 22.32 0.03 5.41 1.01 0.53
我们先列举一下各个性能指标的简单说明。
-
rrqm/s
- 每秒进行merge的读操作数目。 wrqm/s
- 每秒进行merge的写操作数目。 r/s
- 每秒完成的读I/O设备次数。 w/s
- 每秒完成的写I/O设备次数。 rsec/s
- 每秒读扇区数。 wsec/s
- 每秒写扇区数。 rkB/s
- 每秒读K字节数。 wkB/s
- 每秒写K字节数。 avgrq-sz
- 平均每次设备I/O操作的数据大小(扇区)。 avgqu-sz
- 平均I/O队列长度。 await
- 平均每次设备I/O操作的等待时间(毫秒)。 svctm
- 平均每次设备I/O操作的服务时间(毫秒)。 %util
- 一秒中有百分之多少的时间用于I/O操作,或者说一秒中有多少时间I/O队列是非空的。
要理解这些性能指标我们先看下图
IO的执行过程的各个参数 |
(上图中,io合并发生于io调度层非OS buffer cache上,/dev/sda是作用于一个物理磁盘的驱动程序,而/dev/sda1则是在自己这个分区范围里封装调用了/dev/sda的驱动程序?)
上图的左边是iostat显示的各个性能指标,每个性能指标都会显示在一条虚线之上,这表明这个性能指标是从虚线之上的那个读写阶段开始计量的,比如说图中的w/s从Linux IO scheduler开始穿过硬盘控制器(CCIS/3ware),这就表明w/s统计的是每秒钟从Linux IO scheduler通过硬盘控制器的写IO的数量。
结合上图对读IO操作的过程做一个说明,在从OS Buffer Cache传入到OS Kernel(Linux IO scheduler)的读IO操作的个数实际上是rrqm/s+r/s,直到读IO请求到达OS Kernel层之后,有每秒钟有rrqm/s个读IO操作被合并,最终转送给磁盘控制器的每秒钟读IO的个数为r/w;在进入到操作系统的设备层(/dev/sda)之后,计数器开始对IO操作进行计时,最终的计算结果表现是await,这个值就是我们要的IO响应时间了;svctm是在IO操作进入到磁盘控制器之后直到磁盘控制器返回结果所花费的时间,这是一个实际IO操作所花的时间,当await与svctm相差很大的时候,我们就要注意磁盘的IO性能了;而avgrq-sz是从OS Kernel往下传递请求时单个IO的大小,avgqu-sz则是在OS Kernel中IO请求队列的平均大小。
现在我们可以将iostat输出结果和我们前面讨论的指标挂钩了。
平均IO响应时间(IO Response Time) <=> await
IOPS(IO per Second) <=> r/s + w/s
吞吐率(Throughtput) <=> rkB/s + wkB/s
topiostat的应用实例
top观察IO Scheduler的IO合并(IO Merge)
前面说过IO在执行过程中会被合并以提高效率,下面就结合dd命令和iostat命令看一下。
我们先执行dd命令,设置bs参数值为1k,完整命令如下
(dd命令中bs(block size)参数值要为扇区大小的整数倍,因为dd命令在操作系统的设备层上运行,即dd命令直接调用了操作系统的设备层的接口,而如上图所说“从这往下的每个操作都是512字节大小(的整数倍)”)
同时打开另外一个终端执行iostat命令,这里只查看变化那个磁盘的更改,每秒刷新一次数据,完整命令如下
(
iostat -x hdc7 1
hdc7 表示(块)设备名称
1表示每秒刷新一次iostat命令显示的统计数据
附加:
2.这个IO队列和调度的目标是针对某个块设备而言的,换句话说就是每个块设备都有一个独立的IO队列。
3.本篇所涉及的所谓的块设备就是iostat命令里面列出的形如sda,sdb这样的块设备,并不是指物理磁盘。假如一个盘被分成5个分区,那么在这个主题下,5个分区代表5个块设备,每个块设备都有自己独立的IO队列。
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=20764167&id=4053801
)
然后我们可以得到下面的结果
1、-----------------------------------------------------------------
hdc7 0.00 9447.00 0.00 776.00 0.00 80616.00 0.00 40308.00 103.89 480.18 805.95 1.29 100.00
avg-cpu: %user %nice %sys %iowait %idle
0.50 0.00 56.00 43.50 0.00
2、-----------------------------------------------------------------
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
hdc7 0.00 9534.00 0.00 872.00 0.00 81384.00 0.00 40692.00 93.33 274.56 401.19 1.14 99.00
avg-cpu: %user %nice %sys %iowait %idle
2.50 0.00 46.50 14.00 37.00
3、-----------------------------------------------------------------
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
hdc7 0.00 6766.00 1.00 276.00 8.00 58808.00 4.00 29404.00 212.33 197.27 321.66 1.95 54.00
avg-cpu: %user %nice %sys %iowait %idle
0.50 0.00 0.50 0.00 99.00
看结果中第一组数据中的avgrq-sz,为103.89个扇区,磁盘的每个扇区为512字节,因此平均IO大小为103.89*512/1024=52k字节,远远大于我们dd命令时给定的参数1k字节,也就是说IO在中间被合并了。看巨大的wrqm/s也能得出同样的结论。
top附:在Windows中监视IO性能
本来准备写一篇windows中监视IO性能的,后来发现好像可写的内容不多,windows在细节这方面做的不是那么的好,不过那些基本信息还是有的。
在Windows中监视性能基本都用性能监视器了,与IO性能相关的有两个大类,一个是”LogicalDisk”,另外一个是”PhysicalDisk”,”LogicalDisk”更多的是用来监视文件相关的IO性能,而”PhysicalDisk”则是用来监视LUN或者是磁盘卷,下面就列举下与前面所列举的IO性能相关的计数器,具体的自己研究了:
-
单次IO大小
-
- Avg. Disk Bytes/Read
- Avg. Disk Bytes/Write
IO响应时间
-
- Avg. Disk sec/Read
- Avg. Disk sec/Write
IOPS
-
- Disk Reads/sec
- Disk Writes/sec
- Disk Transfers/sec
IO吞吐率
-
- Disk Bytes/sec
- Disk Read Bytes/sec
- Disk Write Bytes/sec
传统磁盘本质上一种机械装置,如FC, SAS, SATA磁盘,转速通常为5400/7200/10K/15K rpm不等。影响磁盘的关键因素是磁盘服务时间,即磁盘完成一个I/O请求所花费的时间,它由寻道时间、旋转延迟和数据传输时间三部分构成。
寻道时间Tseek是指将读写磁头移动至正确的磁道上所需要的时间。寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms。
旋转延迟Trotation是指盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间。旋转延迟取决于磁盘转速,通常使用磁盘旋转一周所需时间的1/2表示。比如,7200 rpm的磁盘平均旋转延迟大约为60*1000/7200/2 = 4.17ms,而转速为15000 rpm的磁盘其平均旋转延迟约为2ms。
数据传输时间Ttransfer是指完成传输所请求的数据所需要的时间,它取决于数据传输率,其值等于数据大小除以数据传输率。目前IDE/ATA能达到133MB/s,SATA II可达到300MB/s的接口数据传输率,数据传输时间通常远小于前两部分时间。因此,理论上可以计算出磁盘的最大IOPS,即IOPS = 1000 ms/ (Tseek + Troatation),忽略数据传输时间。假设磁盘平均物理寻道时间为3ms, 磁盘转速为7200,10K,15K rpm,则磁盘IOPS理论最大值分别为,
IOPS = 1000 / (3 + 60000/7200/2) = 140
IOPS = 1000 / (3 + 60000/10000/2) = 167
IOPS = 1000 / (3 + 60000/15000/2) = 200
固态硬盘SSD是一种电子装置, 避免了传统磁盘在寻道和旋转上的时间花费,存储单元寻址开销大大降低,因此IOPS可以非常高,能够达到数万甚至数十万。实际测量中,IOPS数值会受到很多因素的影响,包括I/O负载特征(读写比例,顺序和随机,工作线程数,队列深度,数据记录大小)、系统配置、操作系统、磁盘驱动等等。因此对比测量磁盘IOPS时,必须在同样的测试基准下进行,即便如何也会产生一定的随机不确定性。通常情况下,IOPS可细分为如下几个指标:
Toatal IOPS,混合读写和顺序随机I/O负载情况下的磁盘IOPS,这个与实际I/O情况最为相符,大多数应用关注此指标。
Random Read IOPS,100%随机读负载情况下的IOPS。
Random Write IOPS,100%随机写负载情况下的IOPS。
Sequential Read IOPS,100%顺序负载读情况下的IOPS。
Sequential Write IOPS,100%顺序写负载情况下的IOPS。IOPS的测试benchmark工具主要有Iometer, IoZone, FIO等,可以综合用于测试磁盘在不同情形下的IOPS。对于应用系统,需要首先确定数据的负载特征,然后选择合理的IOPS指标进行测量和对比分析,据此选择合适的存储介质和软件系统。下面的磁盘IOPS数据来自http://en.wikipedia.org/wiki/IOPS,给大家一个基本参考。
Device IOPS Interface Notes 7200 RPM SATAdrives ~90 IOPS SATA II 10k RPM SATAdrives, queue depth 1 ~130 IOPS SATA II fio -readonly -name iops -rw=randread -bs=512 -runtime=20 -iodepth 1 -filename /dev/sda -ioengine libaio -direct=1
10k RPM Serial Attached SCSIdrives ~140 IOPS SAS 15k RPM Serial Attached SCSIdrives ~180 IOPS SAS 10k RPM SATAdrives, queue depth 24 ~290 IOPS SATA II fio -readonly -name iops -rw=randread -bs=512 -runtime=20 -iodepth 24 -filename /dev/sda -ioengine libaio -direct=1
Simple SLC SSD ~400 IOPS SATA II Intel X25-M G2 (MLC; As of March 2010) ~8,600 IOPS SATA II Intel's data sheet claims 6,600/8,600 IOPS (80GB/160GB version) and 35,000 IOPS for random 4KB writes and reads, respectively. Intel X25-E (SLC; As of March 2009) ~5,000 IOPS SATA II Intel's data sheet claims 3,300 IOPS and 35,000 IOPS for writes and reads, respectively. 5,000 IOPS are measured for a mix. Intel X25-E G1 has around 3 times higher IOPS compared to the Intel X25-M G2. OCZ Z-Drive e84, a PCI Express SLC Solid State Drive 16,000 IOPS PCIe Maximum read/write speed of 800/750 MB/s). G.Skill Phoenix Pro et. al. ~20,000 IOPS SATA III SandForce-1200 based SSD drives with enhanced firmware, states up to 50,000 IOPS, but real-world performance shows for all drives from different manufacturers ~25,000 IOPS for random read and ~15,000 IOPS for random write. ioDrive, a PCI-Express card with Flash 140,000 Read IOPS, 135,000 Write IOPS PCIe ioDrive Duo 250,000+ IOPS PCIe DDRdrive X1, a May 2009 PCI Express based solid-state drive 300,000+ (512B Random Read IOPS) and 200,000+ (512B Random Write IOPS) PCIe Texas Memory System RamSan-20
120,000+ Random Read/Write IOPS PCIe Inlude RAM cache and UltraCapacitor to preserve the memory non-volatile Texas Memory System RamSan-630 Appliance
1,000,000+ Random Read/Write IOPS FC / InfiniBand Violin Memory Appliance 1,000,000+ Random Read/Write IOPS Proprietary interconnect ioDrive Octal (single PCI Express card) 1,000,000+ Random Read/Write IOPS PCIe