目录
- 3. 内存性能监控
- 3.1 内存是什么-虚拟内存和物理内存
- 3.1.1 为什么需要有虚拟内存
- 3.1.2 虚拟内存的原理
- 3.2 内存中的buffer和cache
- 3.2.1 buff/cache
- 3.2.2 **free 与 available**
- 4.文件IO性能监控
- 4.1 IO的两种方式
- 4.1.1 缓存IO
- 4.1.2 直接IO
- 4.2 监控磁盘IO的命令
- 4.2.1 iostat
- 4.2.2 swapon查看分区的使用情况
- 4.2.3 df查看硬盘使用情况
- 4.2.4 du查看目录文件大小
3. 内存性能监控
3.1 内存是什么-虚拟内存和物理内存
3.1.1 为什么需要有虚拟内存
操作系统有虚拟内存和物理内存的概念。在很久以前,还没有虚拟内存的概念,程序寻址用的都是物理地址。程序能寻址的范围是有限的,这取决与CPU的地址线条数。比如在32位的平台下,寻址的范围是2^32也就是4G。如果没有虚拟内存,可能会出现的问题:
- 内存空间的利用率:各个进程对内存的使用会使内存碎片化,在需要malloc分配一块很大的内存空间时,虽然有足够多的空闲内存,但由于不能组成连续的足够大小的内存块而不能被有效利用。
- 内存读写的安全性:物理内存本身是不限制访问的,任何地址都可以读写,而现代操作系统需要实现不同的页面具有不同的访问权限,例如只读的数据等等
- 进程间的安全性:进程运行时的指令是直接操作物理内存的,由于进程没有各自独立的地址空间,一个进程由于错误地执行指令或恶意的代码都可以直接修改其他进程的数据,因此操作系统需要管理起来
- 内存读写的效率:物理内存的大小是有限的,当多个进程同时执行,每个进程都需要分配很大的内存空间时,暂时分配不到资源的进程会暂时拷贝到硬盘中,等待其他进程执行结束后才能被重新加载到内存中;内存频繁的装入装出数据对效率影响很大
3.1.2 虚拟内存的原理
每个进程创建加载的时候,会被分配一个大小为4G(32位下)的“连续”的虚拟地址空间,这个空间不是真实的物理空间,仅仅是每个进程“认为”自己拥有4G的内存,而实际上,它用了多少空间,操作系统就划出多少空间给它;它通常是被分割成多个物理内存碎片,还有一部分存储在外部磁盘存储器上,在需要时才进行数据交换。
更准确一点的说,系统将虚拟内存分割为称为虚拟页(Virtual Page,VP)的大小固定的块,每个虚拟页的大小为P = 2^p字节,类似地,物理内存被分割为物理页(Physical Page,PP),大小也为P字节(物理页也称为页帧(page frame))。
在任意时刻,虚拟页面都分为互不相交的三种:
- 未分配的:系统还未分配(或者创建)的页。未分配的块没有任何数据和它们相关联,因此也就不占用任何磁盘空间
- 未缓存的:没有缓存在物理存储器中的已分配页
- 缓存的:当前缓存在物理存储器中的已分配页
进程开始访问一个地址,可能会经历以下的过程:
- 每次我要访问地址空间上的某一个地址,都要先翻译成实际的物理内存地址
- 所有进程共享这一整块物理内存,每个进程只把自己当前需要的虚拟地址空间映射到物理内存上
- 进程需要知道哪些数据在物理内存上,和物理内存上的地址,这就需要页表来记录;还需要知道哪些不在(可能这部分在磁盘上)
- 页表结构描述了虚拟地址与物理地址的映射关系,页表的每一个表项分为两个部分,第一部分记录是否在物理内存上,第二部分记录物理内存页的地址(如果在的话)
- 当进程访问某个虚拟地址时,先查页表,如果发现对应的数据不在物理内存上,就会发生缺页异常
- 触发缺页异常后,系统会调用内核中的缺页异常处理程序,该程序会选择一个牺牲页(牺牲页的选择有具体的算法,不在此进行讨论),将牺牲页拷回磁盘,并修改牺牲页的虚拟页表为不在物理内存中。接下来,内核再将所需数据的所在页从磁盘拷贝到物理内存中,并建立起页表映射,随后返回。
- 当异常处理程序返回时,它会重新启动导致缺页的指令,再次从虚拟地址开始访问,此时能正常页命中,就可以直接读取物理内存了
3.2 内存中的buffer和cache
图中显示了物理内存Mem和缓缓分区Swap的具体使用情况:
- total列显示系统总的可用物理内存和交换空间的大小
- used列显示已经被使用的物理内存和交换空间的大小
- free列显示还有多少物理内存和交换空间没有
- shared列显示被共享使用的物理内存大小
- buff/cache列显示被buffer和cache使用的物理内存大小
- available列显示还可以被应用程序使用的物理内存大小
3.2.1 buff/cache
为了提高磁盘存取效率, Linux做了一些精心的设计, 除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换), 还采取了两种主要Cache方式:Buffer Cache和Page Cache。前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache有效缩短了 I/O系统调用(比如read,write,getdents)的时间。
- buffer 在操作系统中指 buffer cache, 中文一般翻译为 “缓冲区”。
- 要理解缓冲区,必须明确另外两个概念:“扇区” 和 “块”。扇区是设备的最小寻址单元,也叫 “硬扇区” 或 “设备块”。块是操作系统中文件系统的最小寻址单元,也叫 “文件块” 或 “I/O 块”。
- 每个块包含一个或多个扇区,但大小不能超过一个页面,因此一个页可以容纳一个或多个内存中的块。当一个块被调入内存时,它将存储在一个buffer cache中。每个buffer cache与一个块对应,它相当于是磁盘块在内存中的表示。
- 注意,buffer cache 只有块的概念而没有文件的概念,它只是把磁盘上的块直接搬到内存中而不关心块中究竟存放的是什么格式的文件。
- cache 在操作系统中指 page cache,中文一般翻译为 “页高速缓存”。
- 页高速缓存是内核实现的磁盘缓存。它主要用来减少对磁盘的 I/O 操作。具体地讲,是通过把磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。
- 页高速缓存缓存的是内存页面。缓存中的页来自对普通文件、块设备文件(这个指的就是 buffer cache)和内存映射文件的读写。
- 页高速缓存对普通文件的缓存我们可以这样理解:当内核要读一个文件(比如 /etc/hosts)时,它会先检查这个文件的数据是不是已经在页高速缓存中了。如果在,就放弃访问磁盘,直接从内存中读取。这个行为称为缓存命中。如果数据不在缓存中,就是未命中缓存,此时内核就要调度块 I/O 操作从磁盘去读取数据。然后内核将读来的数据放入页高速缓存中。这种缓存的目标是文件系统可以识别的文件(比如 /etc/hosts)。
- 页高速缓存对块设备文件的缓存就是我们在前面介绍的 buffer cache。因为独立的磁盘块通过缓冲区也被存入了页高速缓存(缓冲区最终是由页高速缓存来承载的)。缓冲区只不过是一种概念上比较特殊的页高速缓存罢了
那么为什么 free 命令不直接称为 cache 而非要写成 buff/cache? 这是因为缓冲区和页高速缓存的实现并非天生就是统一的。在 linux 内核 2.4 中才将它们统一。更早的内核中有两个独立的磁盘缓存:页高速缓存和缓冲区高速缓存。前者缓存页面,后者缓存缓冲区。当你知道了这些故事之后,输出中列的名称可能已经不再重要了。
3.2.2 free 与 available
在 free 命令的输出中,有一个 free 列,同时还有一个 available 列。这二者到底有何区别? free 是真正尚未被使用的物理内存数量。至于 available 就比较有意思了,它是从应用程序的角度看到的可用内存数量。Linux 内核为了提升磁盘操作的性能,会消耗一部分内存去缓存磁盘数据,就是我们介绍的 buffer 和 cache。所以对于内核来说,buffer 和 cache 都属于已经被使用的内存。当应用程序需要内存时,如果没有足够的 free 内存可以用,内核就会从 buffer 和 cache 中回收内存来满足应用程序的请求。所以从应用程序的角度来说,available = free + buffer + cache。不过这只是一个很理想的计算方式,实际中的数据往往有较大的误差。
4.文件IO性能监控
4.1 IO的两种方式
4.1.1 缓存IO
缓存IO又被称为标准IO,大多数文件系统的默认IO操作都是缓存IO。在Linux的缓存IO机制中,数据先从磁盘复制到内核空间的缓冲区,然后从内核空间缓冲区复制到应用程序的地址空间(用户空间)
- 读操作:操作系统检查内核空间有没有需要的数据,如果已经缓存了,那么就从缓存中返回;否则从磁盘中读取数据至内核空间的缓冲区,再将内核空间缓冲区的数据返回
- 写操作,将数据从用户空间复制到内核空间的缓冲区,这时对用户来说写操作就已经完成。至于什么时候将数据写回磁盘,是由操作系统决定的,除非显示调用了sync同步命令
缓存IO的优点:
- 在一定程度上分离了内核和用户空间,保证操作系统本身的安全
- 可以减少磁盘的读写次数,从而提高性能
缓存IO的缺点:
- 在缓存IO机制中,DMA(直接内存访问,Direct Memory Access)方式,可以将数据直接从磁盘读到内核空间的缓存中,或者将数据从内核空间的页缓存直接写回到磁盘上,而不能直接在磁盘和用户空间之间进行传输。这样,数据在传输过程中需要在用户和内核中间之间进行多次拷贝,这些数据的拷贝操作带来的性能开销是比较大的
在DMA的参与下,CPU不再参与数据从磁盘缓冲区到内核缓冲区的拷贝操作。
4.1.2 直接IO
直接IO就是应用程序直接访问磁盘,而不经过内核缓冲区,这样做能够减少一次从内核缓冲区与用户程序地址空间的数据拷贝操作。
例如数据库管理系统这类应用,它们更倾向于选择自己的缓存机制,因为其往往比操作系统更了解数据库中存放的数据,从而提供一种更高效的缓存机制来提高数据库中存取数据的性能。
4.2 监控磁盘IO的命令
4.2.1 iostat
- rrqm/s:每秒对该设备的读请求被合并次数,文件系统会对读取同块(block)的请求进行合并
- wrqm/s:每秒对该设备的写请求被合并次数
- r/s:每秒完成的读次数
- w/s:每秒完成的写次数
- rKB/s:每秒读数据量(KB为单位)
- wKB/s:每秒写数据量(KB为单位)
- avgrq-sz:平均每次IO操作的数据量(扇区数为单位),比如1616.56
- avgqu-sz:平均等待处理的IO请求队列长度,比如2.74
- await:平均每次IO请求响应时间(包括等待时间和处理时间,毫秒为单位),比如w_await 2.97
- svctm:平均每次IO请求的处理时间(毫秒为单位),比如0.72
- %util:采集周期内用于IO操作的时间比率。表示该设备的繁忙程度,比如82.80。例如,如果统计间隔1秒,该设备有0.5秒在处理IO,则该设备的%util = 0.5 / 1 = 50%。一般地,如果该参数是100%,表示设备已经接近满负荷运行
关于await和svctm的差值
- 可以理解为IO请求的响应时间,包括队列等待时间和处理时间,await-svctm差值越小,则说明队列等待时间越短;反之,队列时间越长,说明磁盘IO有性能问题
4.2.2 swapon查看分区的使用情况
查看交换分区的使用情况:swapon -s
swap分区通常被称为交换分区,是一块特殊的磁盘空间,当实际内存不够用时,操作系统会从内存中取出一部分暂时不用的数据,放在交换分区中,从而为当前正在运行的程序腾出足够的内存空间。这种“拆东墙,补西墙”的方式应用在几乎所有的操作系统中。
一般来说,swap分区的容量大小应该大于物理内存的大小,建议是内存的两倍,但不超过2GB
4.2.3 df查看硬盘使用情况
该命令用于查看文件系统的硬盘挂载点和空间使用情况,df -h
4.2.4 du查看目录文件大小
du -lh --max-depth=1