作者:维子 https://segmentfault.com/a/1190000021388785?utm_source=tag_newest
IO 性能对于一个系统的影响是至关重要的。一个系统经过多项优化以后,瓶颈往往落在数据库;而数据库经过多种优化以后,瓶颈最终会落到 IO 。而 IO 性能的发展,明显落后于 CPU 的发展。 Memchached 也好, NoSql 也好,这些流行技术的背后都在直接或者间接地回避 IO 瓶颈,从而提高系统性能。
一、IO 系统的分层
上图层次比较多,但总的就是三部分。磁盘 (存储)、 VM (卷管理)和文件系统 。专有名词不好理解,打个比方说:磁盘就相当于一块待用的空地; LVM 相当于空地上的围墙(把空地划分成多个部分);文件系统则相当于每块空地上建的楼房(决定了有多少房间、房屋编号如何,能容纳多少人住);而房子里面住的人,则相当于系统里面存的数据。
1.1 文件系统 — 数据如何存放?
对应了上图的 File System 和 Buffer Cache 。
File System (文件系统):解决了空间管理的问题 ,即:数据如何存放、读取。
Buffer Cache :解决数据缓冲的问题。对读,进行 cache ,即:缓存经常要用到的数据;对写,进行buffer ,缓冲一定数据以后,一次性进行写入。
1.2 VM 磁盘空间不足了怎么办?
对应上图的 Vol Mgmt 。
VM 其实跟 IO 没有必然联系。他是处于文件系统和磁盘(存储)中间的一层。 VM 屏蔽了底层磁盘对上层文件系统的影响 。当没有 VM 的时候,文件系统直接使用存储上的地址空间,因此文件系统直接受限于物理硬盘,这时如果发生磁盘空间不足的情况,对应用而言将是一场噩梦,不得不新增硬盘,然后重新进行数据复制。而 VM 则可以实现动态扩展,而对文件系统没有影响。另外, VM 也可以把多个磁盘合并成一个磁盘,对文件系统呈现统一的地址空间,这个特性的杀伤力不言而喻。
1.3 存储 — 数据放在哪儿?如何访问?如何提高IO 速度?
对应上图的 Device Driver 、 IO Channel 和 Disk Device
数据最终会放在这里,因此,效率、数据安全、容灾是这里需要考虑的问题。而提高存储的性能,则可以直接提高物理 IO 的性能
1.4 Logical IO vs Physical IO
逻辑 IO 是操作系统发起的 IO ,这个数据可能会放在磁盘上,也可能会放在内存(文件系统的 Cache )里。
物理 IO 是设备驱动发起的 IO ,这个数据最终会落在磁盘上。
逻辑 IO 和物理 IO 不是一一对应的。
二、IO 模型
这部分的东西在网络编程经常能看到,不过在所有IO处理中都是类似的。
2.1 IO 请求的两个阶段:
等待资源阶段:IO请求一般需要请求特殊的资源(如磁盘、RAM、文件),当资源被上一个使用者使用没有被释放时,IO请求就会被阻塞,直到能够使用这个资源。
使用资源阶段:真正进行数据接收和发生。
举例说就是排队和服务。
2.2 在等待数据阶段,IO分为阻塞IO和非阻塞IO。
阻塞IO:资源不可用时,IO请求一直阻塞,直到反馈结果(有数据或超时)。
非阻塞IO:资源不可用时,IO请求离开返回,返回数据标识资源不可用
2.3 在使用资源阶段,IO分为同步IO和异步IO。
同步IO:应用阻塞在发送或接收数据的状态,直到数据成功传输或返回失败。
异步IO:应用发送或接收数据后立刻返回,数据写入OS缓存,由OS完成数据发送或接收,并返回成功或失败的信息给应用。
2.4 Unix的5个IO模型划分
- 阻塞IO
- 非阻塞IO
- IO复用
- 信号驱动的IO
- 异步IO
从性能上看,异步IO的性能无疑是最好的。
2.5 各种IO的特点
阻塞IO:使用简单,但随之而来的问题就是会形成阻塞,需要独立线程配合,而这些线程在大多数时候都是没有进行运算的。Java的BIO使用这种方式,问题带来的问题很明显,一个Socket需要一个独立的线程,因此,会造成线程膨胀。
非阻塞IO:采用轮询方式,不会形成线程的阻塞。Java的NIO使用这种方式,对比BIO的优势很明显,可以使用一个线程进行所有Socket的监听(select)。大大减少了线程数。
同步IO:同步IO保证一个IO操作结束之后才会返回,因此同步IO效率会低一些,但是对应用来说,编程方式会简单。Java的BIO和NIO都是使用这种方式进行数据处理。
异步IO:由于异步IO请求只是写入了缓存,从缓存到硬盘是否成功不可知,因此异步IO相当于把一个IO拆成了两部分,一是发起请求,二是获取处理结果。因此,对应用来说增加了复杂性。但是异步IO的性能是所有很好的,而且异步的思想贯穿了IT系统放放面面。
三、IO 性能的重要指标
最重要的三个指标
3.1 IOPS
IOPS,Input/Output Per Second,即每秒钟处理的I/O请求数量。IOPS是随机访问类型业务(OLTP类)很重要的一个参考指标。
3.1.2 一块物理硬盘能提供多少IOPS?
从磁盘上进行数据读取时,比较重要的几个时间是:寻址时间(找到数据块的起始位置),旋转时间(等待磁盘旋转到数据块的起始位置),传输时间(读取数据的时间和返回的时间)。其中寻址时间是固定的(磁头定位到数据的存储的扇区即可),旋转时间受磁盘转速的影响,传输时间受数据量大小的影响和接口类型的影响(不用硬盘接口速度不同),但是在随机访问类业务中,他的时间也很少。因此,在硬盘接口相同的情况下,IOPS主要受限于寻址时间和传输时间。以一个15K的硬盘为例,寻址时间固定为4ms,传输时间为60s/15000 * 1/2=2ms,忽略传输时间。1000ms/6ms=167个IOPS。
常见磁盘平均物理寻道时间为:
7200RPM(转)/分的STAT硬盘平均物理寻道时间是9ms,平均旋转延迟大约 4.17ms
10000RPM(转)/分的SAS硬盘平均物理寻道时间是6ms ,平均旋转延迟大约 3ms
15000RPM(转)/分的SAS硬盘平均物理寻道时间是4ms,平均旋转延迟大约
2ms
最大IOPS的理论计算方法:IOPS = 1000 ms/ (寻道时间 + 旋转延迟)。忽略数据传输时间。
7200 rpm的磁盘IOPS = 1000 / (9 + 4.17) = 76 IOPS
10000 rpm的磁盘IOPS = 1000 / (6+ 3) = 111 IOPS
15000 rpm的磁盘IOPS =
1000 / (4 + 2) = 166 IOPS
RAID0/RAID5/RAID6的多块磁盘可以并行工作,所以,在这样的硬件条件下, IOPS 相应倍增。假如, 两块15000 rpm 磁盘的话,166 * 2 = 332 IOPS。
维基上列出了常见硬盘的IOPS
SSD 达到了惊人的100,000。 见下图
固态硬盘没有寻道时间和旋转时间。IO耗时是通过地址查找数据耗时,根据芯片颗粒SLC、MLC,中控芯片、队列深度32~64、接口Sata、PCIE的不同,一般负载非太高时是相对固定值(控制在60%利用率)。
IOPS = 1000/IO耗时。因为SSD比较固定,比如Intel 320 SSD对8K avgrq-sz耗时0.1ms,1000/0.1ms=10000 IOPS。
3.1.3 OS的一次IO请求对应物理硬盘一个IO吗?
在没有文件系统、没有VM(卷管理)、没有RAID、没有存储设备的情况下,这个答案还是成立的。但是当这么多中间层加进去以后,这个答案就不是这样了。物理硬盘提供的IO是有限的,也是整个IO系统存在瓶颈的最大根源。所以,如果一块硬盘不能提供,那么多块在一起并行处理,这不就行了吗?确实是这样的。可以看到,越是高端的存储设备的cache越大,硬盘越多,一方面通过cache异步处理IO,另一方面通过盘数增加,尽可能把一个OS的IO分布到不同硬盘上,从而提高性能。文件系统则是在cache上会影响,而VM则可能是一个IO分布到多个不同设备上(Striping)。
所以,一个OS的IO在经过多个中间层以后,发生在物理磁盘上的IO是不确定的。可能是一对一个,也可能一个对应多个。
3.1.4 IOPS 能算出来吗?
对单块磁盘的IOPS的计算没有没问题,但是当系统后面接的是一个存储系统时、考虑不同读写比例,IOPS则很难计算,而需要根据实际情况进行测试。主要的因素有:
存储系统本身有自己的缓存。缓存大小直接影响IOPS,理论上说,缓存越大能cache的东西越多,在cache命中率保持的情况下,IOPS会越高。
RAID级别。不同的RAID级别影响了物理IO的效率。
读写混合比例。对读操作,一般只要cache能足够大,可以大大减少物理IO,而都在cache中进行;对写操作,不论cache有多大,最终的写还是会落到磁盘上。因此,100%写的IOPS要越狱小于100%的读的IOPS。同时,100%写的IOPS大致等同于存储设备能提供的物理的IOPS。
一次IO请求数据量的多少。一次读写1KB和一次读写1MB,显而易见,结果是完全不同的。
当时上面N多因素混合在一起以后,IOPS的值就变得扑朔迷离了。所以,一般需要通过实际应用的测试才能获得。
3.2 IO Response Time
即IO的响应时间。IO响应时间是从操作系统内核发出一个IO请求到接收到IO响应的时间。因此,IO Response time除了包括磁盘获取数据的时间,还包括了操作系统以及在存储系统内部IO等待的时间。一般看,随IOPS增加,因为IO出现等待,IO响应时间也会随之增加。对一个OLTP系统,10ms以内的响应时间,是比较合理的。下面是一些IO性能示例:
- 一个8K的IO会比一个64K的IO速度快,因为数据读取的少些。
- 一个64K的IO会比8个8K的IO速度快,因为前者只请求了一个IO而后者是8个IO。
- 串行IO会比随机IO快,因为串行IO相对随机IO说,即便没有Cache,串行IO在磁盘处理上也会少些操作。
需要注意,IOPS与IO Response Time有着密切的联系。一般情况下,IOPS增加,说明IO请求多了,IO Response Time会相应增加。但是会出现IOPS一直增加,但是IO Response Time变得非常慢,超过20ms甚至几十ms,这时候的IOPS虽然还在提高,但是意义已经不大,因为整个IO系统的服务时间已经不可取。
3.3 Throughput
为吞吐量。这个指标衡量标识了最大的数据传输量。如上说明,这个值在顺序访问或者大数据量访问的情况下会比较重要。尤其在大数据量写的时候。
吞吐量不像IOPS影响因素很多,吞吐量一般受限于一些比较固定的因素,如:网络带宽、IO传输接口的带宽、硬盘接口带宽等。一般他的值就等于上面几个地方中某一个的瓶颈。
3.4 一些概念
3.4.1 IO Chunk Size
即单个IO操作请求数据的大小。一次IO操作是指从发出IO请求到返回数据的过程。IO Chunk Size与应用或业务逻辑有着很密切的关系。比如像Oracle一类数据库,由于其block size一般为8K,读取、写入时都此为单位,因此,8K为这个系统主要的IO Chunk Size。IO Chunk Size 小,考验的是IO系统的IOPS能力;IO Chunk Size 大,考验的时候IO系统的IO吞吐量。
3.4.2 Queue Deep
熟悉数据库的人都知道,SQL是可以批量提交的,这样可以大大提高操作效率。IO请求也是一样,IO请求可以积累一定数据,然后一次提交到存储系统,这样一些相邻的数据块操作可以进行合并,减少物理IO数。而且Queue Deep如其名,就是设置一起提交的IO请求数量的。一般Queue Deep在IO驱动层面上进行配置。
Queue Deep与IOPS有着密切关系。Queue Deep主要考虑批量提交IO请求,自然只有IOPS是瓶颈的时候才会有意义,如果IO都是大IO,磁盘已经成瓶颈,Queue Deep意义也就不大了。一般来说,IOPS的峰值会随着Queue Deep的增加而增加(不会非常显著),Queue Deep一般小于256。
3.4.3 随机访问(随机IO)、顺序访问(顺序IO)
随机访问的特点是每次IO请求的数据在磁盘上的位置跨度很大(如:分布在不同的扇区),因此N个非常小的IO请求(如:1K),必须以N次IO请求才能获取到相应的数据。
顺序访问的特点跟随机访问相反,它请求的数据在磁盘的位置是连续的。当系统发起N个非常小的IO请求(如:1K)时,因为一次IO是有代价的,系统会取完整的一块数据(如4K、8K),所以当第一次IO完成时,后续IO请求的数据可能已经有了。这样可以减少IO请求的次数。这也就是所谓的预取。
随机访问和顺序访问同样是有应用决定的。如数据库、小文件的存储的业务,大多是随机IO。而视频类业务、大文件存取,则大多为顺序IO。
3.4.4 选取合理的观察指标:
以上各指标中,不用的应用场景需要观察不同的指标,因为应用场景不同,有些指标甚至是没有意义的。
随机访问和IOPS: 在随机访问场景下,IOPS往往会到达瓶颈,而这个时候去观察Throughput,则往往远低于理论值。
顺序访问和Throughput:在顺序访问的场景下,Throughput往往会达到瓶颈(磁盘限制或者带宽),而这时候去观察IOPS,往往很小。
3.5 标定
与 CPU 不同,不同环境下,磁盘的性能指标与厂家标称会不一致。因此,在性能分析前,对所在的计算环境进行标定是很有必要的。
目前主流的第三方IO测试工具有fio、iometer 和 Orion,这三种工具各有千秋。
fio 在 Linux 系统下使用比较方便,iometer 在 window 系统下使用比较方便,Orion 是 oracle 的IO测试软件,可在没有安装 oracle 数据库的情况下模拟 oracle 数据库场景的读写。
3.5.1 FIO
FIO是测试IOPS的非常好的工具,用来对硬件进行压力测试和验证,支持13种不同的I/O引擎,包括:sync,mmap,libaio,posixaio,SGv3,splice,null,network,syslet,guasi,solarisaio等等。
3.5.1.1 安装FIO
在FIO官网地址下载最新文件,解压后./configure、make、make install 就可以使用fio了。
3.5.1.2 fio参数解释
可以使用fio -help查看每个参数,具体的参数左右可以在官网查看how to文档,如下为几个常见的参数描述
filename=/dev/emcpowerb 支持文件系统或者裸设备,-filename=/dev/sda2或-filename=/dev/sdb
direct=1 测试过程绕过机器自带的buffer,使测试结果更真实
rw=randwread 测试随机读的I/O
rw=randwrite 测试随机写的I/O
rw=randrw 测试随机混合写和读的I/O
rw=read 测试顺序读的I/O
rw=write 测试顺序写的I/O
rw=rw 测试顺序混合写和读的I/O
bs=4k 单次io的块文件大小为4k
bsrange=512-2048 同上,提定数据块的大小范围
size=5g 本次的测试文件大小为5g,以每次4k的io进行测试
numjobs=30 本次的测试线程为30
runtime=1000 测试时间为1000秒,如果不写则一直将5g文件分4k每次写完为止
ioengine=psync io引擎使用pync方式,如果要使用libaio引擎,需要yum install libaio-devel包
rwmixwrite=30 在混合读写的模式下,写占30%
group_reporting 关于显示结果的,汇总每个进程的信息
此外
lockmem=1g 只使用1g内存进行测试
zero_buffers 用0初始化系统buffer
nrfiles=8 每个进程生成文件的数量
3.5.1.3 fio测试
测试场景
100%随机,100%读, 4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=rand_100read_4k
100%随机,100%写, 4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=rand_100write_4k
100%顺序,100%读 ,4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=sqe_100read_4k
100%顺序,100%写 ,4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=sqe_100write_4k
100%随机,70%读,30%写 4K
fio -filename=/dev/emcpowerb -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=4k -size=1000G -numjobs=50 -runtime=180 -group_reporting -name=randrw_70read_4k
实际测试
fio -filename=/dev/sda -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=100 -group_reporting -name=mytest -ioscheduler=noop
上述命令,进行随机读写测试。队列深度为1。
VM (long time running) 是 测试用的虚拟机。这台 VM的磁盘性能极低。只有两位数。同一台 ESXi 上的另一台 VM(new build ),磁盘性能很正常。两者的区别在于,前者不是新装,而是一直跑
volume test 。后者是新安装的。
3.6 分析工具
3.6.1 iostat
用途:主要用于监控系统设备的IO负载情况,iostat首次运行时显示自系统启动开始的各项统计信息,之后运行iostat将显示自上次运行该命令以后的统计信息。用户可以通过指定统计的次数和时间来获得所需的统计信息。
缺点:iostat有一个弱点,就是它不能对某个进程进行深入分析,仅对系统的整体情况进行分析。iostat属于sysstat软件包。可以用yum
install sysstat 直接安装。
命令格式:
iostat[参数][时间][次数]
命令参数:
• -C 显示CPU使用情况
• -d 显示磁盘使用情况
• -k 以 KB 为单位显示
• -m 以 M 为单位显示
• -N 显示磁盘阵列(LVM) 信息
• -n 显示NFS 使用情况
• -p[磁盘] 显示磁盘和分区的情况
• -t 显示终端和CPU的信息
• -x 显示详细信息
• -V 显示版本信息
如上图,每1秒钟显示一次报告
iostat -x 2 6 /dev/sda1
每两秒钟显示一次sda1的统计报告,共显示6次。
CPU 属性值
• %user:CPU处在用户模式下的时间百分比。
• %nice:CPU处在带NICE值的用户模式下的时间百分比。
• %system:CPU处在系统模式下的时间百分比。
• %iowait:CPU等待输入输出完成时间的百分比。
• %steal:管理程序维护另一个虚拟处理器时,虚拟CPU的无意识等待时间百分比。
• %idle:CPU空闲时间百分比。
设备属性值
备注:
• 如果%iowait的值过高,表示硬盘存在I/O瓶颈,
• %idle值高,表示CPU较空闲,
• 如果%idle值高但系统响应慢时,有可能是CPU等待分配内存,此时应加大内存容量。
• %idle值如果持续低于10,那么系统的CPU处理能力相对较低,表明系统中最需要解决的资源是CPU。
磁盘每一列的含义如下:
• 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 操作的数据大小(扇区)
• avgqu-sz: 平均 I/O 队列长度。
• await: 平均每次设备 I/O 操作的等待时间(毫秒)
• r_await:每个读操作平均所需的时间=[Δrd_ticks/Δrd_ios]
不仅包括硬盘设备读操作的时间,还包括了在kernel队列中等待的时间。
• w_await:每个写操作平均所需的时间=[Δwr_ticks/Δwr_ios]
不仅包括硬盘设备写操作的时间,还包括了在kernel队列中等待的时间。
• svctm: 平均每次设备 I/O 操作的服务时间(毫秒)
• %util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。
备注:
• 如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。
• 如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;
• 如果 await 远大于 svctm,说明I/O 队列太长,io响应太慢,则需要进行必要优化。
• 如果avgqu-sz比较大,也表示有当量io在等待。
3.6.2 iotop
在某些场景下,我们需要找到占用IO特别大的进程,然后关闭它,需要知道PID或者进程名称,这就需要用到iotop。iotop是一个检测Linux系统进程IO的工具,界面类似top,如下图。
iotop和top一样,也可以通过键入相应键,触发排序选项,例如按o可以在IO活动进程和所有进程之间切换。可以通过左右箭头,选择响应的列进行数据排序。
iotop的常用参数如下:
-h, --help 查看帮助信息
-o, --only 只查看有IO操作的进程
-b, --batch 非交互模式
-n, --iter= 设置迭代次数
-d, --delay 刷新频率,默认是1秒
-p, --pid 查看指定的进程号的IO,默认是所有进程
-u, --user 查看指定用户进程的IO,默认是所有用户
-P, --processes 只看进程,不看线程
-a, --accumulated 看累计IO,而不是实时IO
-k, --kilobytes 以KB为单位查看IO,而不是以最友好的单位显示
-t, --time 每行添加一个时间戳,默认便开启--batch
-q, --quit 不显示头部信息
3.6.3 blktrace
blktrace是一柄神器,很多工具都是基于该神器的:ioprof,seekwatcher,iowatcher,这个工具基本可以满足我们的对块设备请求的所有了解。
blktrace的原理
一个I/O请求,从应用层到底层块设备,路径如下图所示:
从上图可以看出IO路径是很复杂的。这么复杂的IO路径我们是无法用短短一篇小博文介绍清楚的。我们将IO路径简化一下:
一个I/O请求进入block layer之后,可能会经历下面的过程:
- Remap: 可能被DM(Device Mapper)或MD(Multiple Device, Software RAID) remap到其它设备
- Split: 可能会因为I/O请求与扇区边界未对齐、或者size太大而被分拆(split)成多个物理I/O
- Merge: 可能会因为与其它I/O请求的物理位置相邻而合并(merge)成一个I/O
- 被IO Scheduler依照调度策略发送给driver
- 被driver提交给硬件,经过HBA、电缆(光纤、网线等)、交换机(SAN或网络)、最后到达存储设备,设备完成IO请求之后再把结果发回。
blktrace 能够记录下IO所经历的各个步骤:
我们一起看下blktrace的输出长什么样子:
第一个字段:8,0 这个字段是设备号 major device ID和minor device ID。
第二个字段:3 表示CPU
第三个字段:11 序列号
第四个字段:0.009507758 Time
Stamp是时间偏移
第五个字段:PID 本次IO对应的进程ID
第六个字段:Event,这个字段非常重要,反映了IO进行到了那一步
第七个字段:R表示 Read,
W是Write,D表示block,B表示Barrier Operation
第八个字段:223490+56,表示的是起始block number 和 number of blocks,即我们常说的Offset 和 Size
第九个字段:
进程名
其中第六个字段非常有用:每一个字母都代表了IO请求所经历的某个阶段。
Q – 即将生成IO请求
|
G – IO请求生成
|
I – IO请求进入IO Scheduler队列
|
D – IO请求进入driver
|
C – IO请求执行完毕
注意,整个IO路径,分成很多段,每一段开始的时候,都会有一个时间戳,根据上一段开始的时间和下一段开始的时间,就可以得到IO 路径各段花费的时间。
注意,我们心心念念的service time,也就是反应块设备处理能力的指标,就是从D到C所花费的时间,简称D2C。
而iostat输出中的await,即整个IO从生成请求到IO请求执行完毕,即从Q到C所花费的时间,我们简称Q2C。
3.6.4 iowatcher
仅仅查看数据进行分析,非常的不直观。工具 iowatcher 可以把 blktrace 采集的信息,转化为图像和动画,方便分析。
iowatcher -t sda.blktrace.bin -o disk.svg
iowatcher -t sda.blktrace.bin --movie -o disk.mp4
首先,我们看 VM volume test 的图像:
参考
说说IO(一)- IO的分层
说说IO(二)- IO模型
说说IO(三)- IO性能的重要指标
说说IO(四)- 文件系统
说说IO(五)- 逻辑卷管理
说说IO(六)- Driver &
IO Channel
说说IO(七)-
RAID
说说IO(八)-
三分天下
磁盘性能分析
IO测试工具之fio详解
blktrace分析IO