Linux性能之磁盘I/O

时间:2021-11-18 08:47:12

磁盘I/O是任何Linux系统中最低速的部分。这主要是由于它与CPU的距离较远,还有就是磁盘需要机械地运动才能工作(就是磁盘通过转动然后寻找文件位置)。以下描述了几种内核获取I/O数据的方式,从磁盘到内存,或者从内存到磁盘。

以内存页的形式读写数据:Linux内核将磁盘分割成页式结构,许多Linux系统默认页的大小为4K。内存读写磁盘以4K页面大小进行。输入下面命令查看(注意这里不能直接使用time):

/usr/bin/time -v date

运行上面的命令后,会有一个Page size(bytes):4096.

Page size (bytes): 4096

主要与次要页面错误(MPF与MnPF):Linux使用一个虚拟内存层映射到物理地址空间。这种映射是按需进行的,当一个进程开始,内核仅映射它所需要的。当一个程序开始运行,内核首先搜索CPU缓存然后是物理内存,如果数据在任意其中一个中都不存在,内核将会声明一个主要页面错误(MPF)。MPF就是到磁盘子系统中检索页面然后把它们缓存到RAM里面。

一旦内存页面映射到缓存区,内核利用这些页面生成一个次要页面错误(MnPF)。MnPF保存系统时间通过重用内存中的一个页面,而不是将它放回磁盘。以下的例子中将会展示一个应用程序启动的时候有多少个MPF和MnPF,一般首次启动,MPF多一些:

/usr/bin/time -v evolution
结果:

Major (requiring I/O) page faults: 163
Minor (reclaiming a frame) page faults: 5918
第二次运行结果:

Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 5581
文件 缓冲区高速缓存(FIle Buffer Cache):内核使用这个用来减少MPFs,增大MnPFs。由于随着时间的推移,系统产生大量的I/O。缓存区高速缓存也将会继续增长,直到内存不足,内核需要释放出来一些页面用于其他用处的时候,操作系统将会离开这些内存中的页面。最终的结果是许多系统管理员看到少量的空闲内存进而担心,实际中,操作系统只是很好使用它的高速缓存。可通过查看/proc/meminfo查看。

# cat /proc/meminfo
MemTotal: 2075672 kB
MemFree: 52528 kB
Buffers: 24596 kB
Cached: 1766844 kB
可以看到此系统2G内存,52MB内存空闲,24MB分配给磁盘写操作(Buffers )。从磁盘读取的1.7GB的页面在内存中(就是缓存Cached)。

内核通过MnPF机制使用这些,而不是把所有的页面从磁盘中拷贝出来。从这些统计的数据中判决操作系统是否过载是不可能的,我们只是看了其中的一部分数据。

Linux内核中的内存页面种类一般有三种,如下:

可读页面这些页面的数据通过硬盘读入,并且是只读的且是硬盘支持的。这些页面存在于缓存区高速缓存内,包含有永不修改的静态文件、二进制文件和库文件。当内核需要这些文件的时候,内核将他们拷贝到内存。如果可用的内存空间过小,内核将会“偷”出来这些页面,然后把它们放到空闲的列表中,引起一个程序必须执行MPF然后将它们拷贝回来。

脏页面这些页面的数据在内存中已经被内核修改,所以这些页面需要使用pdflush进程同步回磁盘。在可使用内存很少的情况下,kswapd配合pdflush将这些页面写入到磁盘确保内存中有足够的空间。

匿名页面这些页面的数据属于一个进程,但是没有任何的文件或者后备存储器与它们相关。它们不能同步回磁盘。在内存紧张的情况下,kswapd将这些数据写入到swap分区作为临时存储,当RAM足够用的时候再读取回来。

页面数据写入到磁盘:

      通过调用fsync()或者sync()系统调用,应用程序本身可能立刻会选择写脏页面到磁盘。这些系统调用声明一个直接的请求到I/O调度器。如果一个应用程序没有调用这些系统调用,那么pdflush内核进程每隔一段时间运行,晶这些页面数据写入磁盘。


我们说到底还是要对Linux系统 的I/O状态进行监控,找出系统I/O的瓶颈。监控I/O可使用的工具有top、vmstat、iostat、sar。这些输出很相似,但是每一个工具又关注的是不同的方面,主要显示出这方面的性能。引起I/O瓶颈的条件有以下几种:

1、计算每秒的I/O

       每一个I到磁盘的/O请求都占用这一段确定的时间,主要是由于磁盘必须旋转着以寻找到磁头。磁盘的旋转经常涉及到“旋转延时(RD)”,磁头的移动称为“磁盘定位(DS)”。磁盘的RD是以设备的RPM(ps:一分钟多少转)为基础的,RD是绕着磁盘半转的,为了说清楚这个问题,下面举个例子。

怎么计算10K RPM的设备的RD?

一秒钟转的圈:10000/60=166RPS,所以转一圈所花费的时间就是1/166=0.006s,也就是说转一圈花费0.006*1000毫秒=6ms。按照定义RD=6ms/2=3ms。在与平均的查找时间3ms相加,再加上2ms的内部传输延时,则一秒钟可处理的I/O数量为1000/(3+3+2)=125IOPS。

所以可以看出一个10K RPM的磁盘,当一个应用程序发起一个I/O请求时候,需要花费平均8ms的时间去服务于那和I/O。I/O请求的数量通常是由IOPS来衡量。10K RPM的磁盘一般有120到150的IOPS。测试有效的IOPS时候,可以用IOPS的总量除以读入或者写入数据的I/O的数量。

2、随机I/O与连续I/O

每秒I/O多少KB和系统的工作负载相关。Linux系统有两种不同的工作负载,分别是连续的和随机的。

首先看下顺序I/O,通过iostat命令可以查看IOPS和处理数据时候I/O的数量。顺序工作负载需要一次顺序读取大量的数据,这种应用程序如企业级数据库,需要执行大量的查询和获取流媒体服务数据。在连续工作负载下,每个I/O通道KB的速度是高速率。连续工作负载的性能依赖于移动大量的数据尽可能地快。如果每个I/O都耗费时间,要可能多的获取那个I/O上的数据。可以通过使用下面的命令来查看I/O的情况:

# iostat -x 1
avg-cpu: %user %nice %sys %idle0.00 0.00 57.1 4 42.86Device:   rrqm/s wrqm/s   r/s   w/s     rsec/s wsec/s     rkB/s  wkB/s     avgrq-sz  avgqu-sz  await    svctm   %util/dev/sda  0.00   12891.43 0.00  105.71  0.00   106080.00  0.00   53040.00  1003.46   1099.43   3442.43  26.49   280.00/dev/sda1 0.00   0.00     0.00  0.00    0.00   0.00       0.00   0.00      0.00      0.00      0.00     0.00    0.00/dev/sda2 0.00   12857.14 0.00  5.71    0.00   105782.86  0.00   52891.43  18512.00  559.14    780.00   490.00  280.00/dev/sda3 0.00   34.29    0.00  100.00  0.00   297.14     0.00   148.57    2.97      540.29    3594.57  24.00   240.00
从上面可以看出有效I/O的速率是用(rkB/s)除以(r/s)或者是用(wkB/s)除以(w/s)。所以磁盘sda的速率是53040/105=505kB per I/O。

下面介绍随机I/O,随机I/O工作负载不是根据数据的大小,依据一个磁盘中可用的IOPS的数量。Web和邮件服务器是随机获取工作负载的。I/O请求是很少的。随机工作负载依赖于一次可以处理多少请求。因此,磁盘可用IOPS的数量是至关重要的。

avg-cpu: %user %nice %sys %idle
2.04 0.00 97.96 0.00
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/sda 0.00 633.67 3.06 102.31 24.49 5281.63 12.24 2640.82 288.89 73.67 113.89 27.22 50.00
/dev/sda1 0.00 5.10 0.00 2.04 0.00 57.14 0.00 28.57 28.00 1.12 55.00 55.00 11.22
/dev/sda2 0.00 628.57 3.06 100.27 24.49 5224.49 12.24 2612.24 321.50 72.55 121.25 30.63 50.00
/dev/sda3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
在随机工作负载情况下,磁盘的速率是2640/102=23kB per I/O。

操作系统没有足够的内存适应所有的I/O请求,就要开始使用swap分区。和文件系统I/O一致,写入swap分区相当耗时。如果操作系统的RAM被耗尽,那么需要在swap分区内大量创建页表。如果交换分区和数据试图访问位置在同一个文件系统上,那么操作系统将进入争夺I/O路径的状态。这将引起系统性能完全降低。如果一个页面既不能读或者不能写回磁盘,它们将永远停留在RAM里面。如果这些数据停留地太久,内核需要将需要释放一些RAM。现在的问题是I/O通道阻塞,无法进行任何操作。这将不可避免地导致内核崩溃,然后系统挂掉!


I/O性能总结:

1、任何时候CPU是等待I/O的状态,那么磁盘是超载的。

2、计算出磁盘可维持的IOPS的数目。

3、检测程序需要随机磁盘接入还是连续磁盘接入。

4、通过比较等待时间和服务时间来监控低速磁盘。

5、监控交换分区和文件系统以保证swap分区没有争夺文件系统I/O。