概述
最近在搞一个小东西,要使用Linux的sar -B命令。而后我发现一个小问题,就是那些输出项的含义,明面上一眼就能看懂,但是仔细思考,却有点拿捏不定它对系统的影响。
所以查找了一些资料,记录一下我对这些输出的理解。这篇文章会从Linux内核的角度去看待那些输出。
在Ubuntu 18.04上执行man sar能够看到-B选项的含义:Report paging statistics.
执行之后的样子形如:
同样在man sar里面也有解释每一个条目的意思,熟悉的读者可以直接跳过这个部分:
- pgpgin/s: Total number of kilobytes the system paged in from disk per second.
- pgpgout/s: Total number of kilobytes the system paged out to disk per second.
- fault/s: fault/s: Number of page faults (major + minor) made by the system per second. This is not a count of page faults that generate I/O, because some page faults can be resolved without I/O.
- majflt/s: Number of major faults the system has made per second, those which have required loading a memory page from disk.
pgfree/s: Number of pages placed on the free list by the system per second.
pgscank/s: Number of pages scanned by the kswapd daemon per second.
pgscand/s: Number of pages scanned directly per second.
pgsteal/s: Number of pages the system has reclaimed from cache (pagecache and swapcache) per second to satisfy its memory demands.
%vmeff: Calculated as pgsteal / pgscan, this is a metric of the efficiency of page reclaim. If it is near 100% then almost every page coming off the tail of the inactive list is being reaped. If it gets too low (e.g. less than 30%) then the virtual memory is having some difficulty. This field is displayed as zero if no pages have been scanned during the interval of time.
选项含义
如果学过操作系统原理,那么对上面的很多条目都有一些熟悉感。现代计算机的内存管理基本上都是一个套路,这个套路就是分页(Paging)。一般而言,操作系统将虚拟地址空间划分成固定大小的“页(Page)”,比如说,现在的Linux默认使用的页大小是4KB,该参数可以通过命令getconf PAGESIZE
查看。操作系统使用页表来管理页。而且,最重要的是,页是操作系统内存管理的最小单元。
但是,系统运行的进程所要求的内存,往往大于实际的物理内存的大小,在狼多肉少的情况下,就要考虑怎么合理分配资源。于是就诞生了一种称为swap的技术。swap其实很简单,就是在物理内存不足的时候,操作系统考虑将一部分内存数据“刷”到文件系统中(简单来说,就是磁盘上)。而Linux为了提高读写效率,会将一部分文件缓存在内存中,那么也会逐渐消耗完所有的物理内存。这个时候,一般会将一些很长时间没有运行的程序交换到磁盘上,以释放出内存供新的程序使用。
pgpgin/s和pgpgout/s
到这里,也就是了解了pgpgin/s和pgpgout/s两个指标的意义。它们展示的就是Linux系统在每秒内,换进换出的内存大小。注意的是,这两个指标的单位是KB,而不是页数。可以想到的是,这两个指标,越大表明物理内存越不够。直接访问内存和从swap中加载比起来,要快至少一个数量级。因此,这两个数字越高,性能惩罚也就越严重。
我看过一个典型的案例,就是在JVM内存回收的时候,因为要扫描存活对象,而触发了大量的pagein和pageout,导致垃圾回收时间显著拉长。
这里要额外讨论的一个是,Linux系统下有一个参数可以控制操作系统在什么情况下开始将内存交换到磁盘上:swappiness
。这个参数假如设置到10,那么表明物理内存使用到90%的时候就会开始交换。很多应用的性能都会受到该设置的影响,典型的如kafka。kafka就是利用page cache将随机写转化为顺序写以获得良好的性能。该参数可以通过命令cat /proc/sys/vm/swappiness
来查看。比如在我买的贫下中农版阿里云上,该值是60。
fault/s和majflt/s
这两个选项,只是说了一件事,就是页错误(Page Fault,也叫页缺失),与之相关的一个耳熟能详的东西就是缺页中断。它是指程序试图访问一个存在于虚拟地址空间,但是并未被映射到实际物理内存的情况。
页缺失一般来说有两种(那种访问的地址都不在虚拟地址空间的错误,我觉得怎么都不算页缺失……):Major Page Fault和Minor Page Fault:
Major Page Fault: 这个就是通俗意义上的页缺失,也就是该页在此时并没有被加载到物理内存中。操作系统这个时候就要找到一个空闲的页,或者一个使用中的页,写到磁盘上,然后从MMU中注销;而后读入选定的页,并向MMU注册。这一大串的操作下来,基本上可以判定,性能降低了极多;
Minor Page Fault: 一般人都不知道这个鬼东西,尤其是那些使用高级编程语言的(越高级越不知道)。出现这种情况的最常见的原因就是进程共享内存,操作系统为其中的一些程序注册了该页,但是并没有为另外的程序注册。另外一种可能是,在MMU上注销了,但是还没来得及刷新到磁盘。不论是哪种情况,可以肯定的是该页一定已经在物理内存中了,操作系统只需要付出少量的代价就能恢复过来;
很显然,这两个选项和前面提到的pgpgin/s、pgpgout/s有很强的关联性。基本上,它们的变化趋势是一致的。数值越大,也意味着性能越糟糕。尤其是majflt/s的数值。而fault/s和majflt/s的差则能计算出Minor Page Fault——该值如果很大,也是一个很奇怪的地方,要小心优化了。
pgfree/s
这个选项很简单,就是每秒放回空闲链表的页的数量。
Linux是使用空闲链表的方法来管理内存的。当一个页不再被使用的时候,它就会被放回去空闲链表。
理论上来说,这个值高点可能会比较好。但是我对此持有一种怀疑的态度。因为pgfree/s每秒越高,意味着每秒有很多进程释放了内存,但是,如果一直持续一段时间,是否也意味着进程在频繁的申请内存,而后又释放?
毕竟,池子的水就那么多,频繁的往里面倒水,也意味着有人频繁的从里面舀水,毕竟也没别的池子可以搞到水了。
pgscank/s和pgscand/s
pgscank我猜测是page scanned by kswapd的简写,而s和pgscand则是page scanned directly的简写。
kswapd是Kernel Swap Daemon的简写。它代表的是一个内核线程。该线程的任务是“keep the memory management system operating efficiently”。大体上来说,它就是一个定时任务,定时查看系统的空闲页,如果数量比较少,它叫要开始将页置换出去磁盘,以腾出物理内存。一般来说,它会清理page cache(kafka再次中枪)、共享页面和discarding pages。有意思的是,这个线程并不是一次清理完这些东西,而是清理个四个页面就收手了。感觉就是为了避免一次清理太多影响正在运行的进程。
而pgscand则可以理解为kswapd的同步版本。我觉得,pgscand的数值大应该比pgscank数值大更加可怕。
pgsteal/s
这个选项,就是代表每秒从page cache和swap cache中回收的页数量。它和pgscank/s、pgscand/s有很强的相关性。要知道的是,操作系统会尽量避免频繁的IO操作,毕竟IO操作太消耗资源了。所以才会page cache和swap cache两个东西,它们分别表示的是映射到磁盘的内存缓存和映射到交换区的内存缓存。所以这个参数代表的是刷新到磁盘的频率。
影响到磁盘刷新page cache的参数主要有两个vm.dirty_ratio和vm.dirty_background_ratio。
%vmeff
理解了前面的参数,理解这个就不难了,它是pgsteal/pgscan的值,实际上也就是pgsteal/(pgscank+pgscand)。它后面还有一大段的话。总结下来就是这个东西越低就越糟糕。
我现在尝试解释一下这个东西。前面提到过,page scan其实就是要找到可以回收的页,而后将对应的物理内存释放出来;而前面还提到,操作系统会尽量避免IO操作,所以,也就是意味着,page scan得到的页,并不会直接被写到磁盘里面。
于是就出现了这样的情况,page scan得到的也还继续驻留在物理内存里面,期望得到释放的内存并没有被释放。所以才会有越低越糟糕的说法。
但是一个很奇特的是,如果page scan得到的结果是0(也就是分母是0),那么结果也是0.所以0通常会有两种可能,一种就是page scan为0个页面,这当然算是好事(?)。因为之前我们提到说,如果要是内存不足的话,kswapd就会清理一些页面。
另外一种可能就是,page steal为0。这就很可怕了,它表示在采集数据的这个时间间隔内,没有任何的page cache和swap cache被刷新到磁盘。
所以,保险起见,要是这个数值低了,或者为0,都要引起重视了。
欢迎关注公众号:
白玉京过客
网友评论