Date

原文Linux System and Performance Monitoring,作者Darren Hoch。

5.0 虚拟内存相关

虚拟内存使用磁盘作为内存的扩展,这样可用的“内存”就更多了。在内存不够时,内核会把最近没有使用的内存块写到磁盘上去。当这部分内存再次被访问时,会把这部分内容再从磁盘读取到物理内存中。这些操作对用户是完全透明的,Linux上的应用程序只是看到有大量的内存可用,但是不知道这些“内存”有部分是存储在磁盘上的。毫无疑问,读写磁盘比读写真正的内存要慢得多(顺序读写大概比内存慢1000倍),因此程序读写内存的时候,如果使用了大量的虚存,程序运行就慢了。磁盘作为虚存使用的那部分叫做交换空间/分区(swap space)。

5.1 虚存页

虚存是按页进行划分的,X86架构上的虚存页大小是4KB。内核进行虚存读写的时候,是按页进行的。内核在某些时候会将内存页写到交换空间和文件系统中。

5.2 内存同步(原文:kernel memory paging)

内存同步是一个常见的操作,不要和内存交换(页置换)搞混淆了。定期将内存同步到磁盘的过程称为内存映射。运行一段时间后,程序可能会慢慢将内存耗尽。在某个时刻,内核为了分配内存给其他程序(或者当前程序),可能需要将最近没有使用的内存置换到磁盘上去,如果之前已经把内存同步到了磁盘上,此时 swapping的操作效率就提高了(不需要在swap前将内容同步到磁盘了)。

5.3 内存回收机制

内存回收机制是为了获取可用的物理内存,其挑选牺牲页的算法因内类型而异。一些页类型如下:

  • Unreclaimable——锁住的、内核使用的、保留的页
  • Swappable——匿名内存页,和交换分区相关的内存页
  • Syncable——和文件系统相关的内存页
  • Discardable——静态页、已废弃的页

除了不可回收页,其他类型页都可能被回收。

内存回收主要的有两大机制:kswapd和“Low on Memory Reclaim”。

5.4 kswapd

守护进程kswapd的作用是保证有一定的空闲内存可用。内核中有pages_high和pages_low两个指标,如果可用内存低于pages_low,kswapd进程开始尝试释放内存,每次释放32页的内存直到可用内存高于pages_high。

kswapd会执行如下的操作:

  • 如果页面没有修改,将该页面放到空闲列表
  • 如果页面已修改且是和文件系统相关的,将该页面内容写到磁盘
  • 如果页面已修改且不是和文件系统相关的(匿名页,对应到交换分区),将该页面内容写到交换设备

5.5 通过pdflush完成内存同步(原文kernel paging with pdflush)

守护进程pdflush的作用是同步文件系统相关的内存页(Syncable)到磁盘。换句话说,当一个文件的内存副本被修改时,pdflush会将修改写回磁盘。

当内存中的脏页超过10%时,pdflush将同步这些脏页到磁盘,10%这个参数值可由内核的vm.dirty_background_ratio调整。

绝大部分情况下,pdflush和内存回收机制是相互独立的。当内核调用Low on Memory Reclaim时,除了其他释放内存的操作,LMR还调用pdflush来同步过期页。

5.6 案例分析

vmstat工具在统计CPU使用的同时也统计了虚存的使用情况。下面是vmstat输出中和虚存相关的一些指标:

列名 含义
swpd 当前使用的虚存数量,单位KB。当空闲内存达到下限时,会有更多的数据被置换到交换分区
free RAM当前的可用内存,单位KB。
buff 物理内存作为read()和write()操作缓冲区部分的大小,单位KB。
cache 物理内存映射到进程地址空间的大小,单位KB。
so 写到交换分区的数据量,单位KB
si 从交换分区写到RAM的数据量,单位KB
bo RAM中置换到文件系统或者交换分区的磁盘块数量
bi 从文件系统或者交换分区置换到RAM中的磁盘块的数量

下面vmstat的输出,可以看出在一个IO型应用的尖峰时刻,有大量的虚存使用:

image

从上面的输出中,我们可以得到以下推论:

  • 大量的磁盘块(bi)从文件系统交换到了内存中。这个可以通过cache的增长明显看出来。
  • 在最后这段时间内,尽管数据从磁盘交换到内存中耗用了RAM,但空闲内存(free)一直保持在17MB。
  • 为了维持可用的空闲内存,kswapd挪用了读写缓存(buff),并将这些内存加入到空闲内存表中。这个可以从buff的减少看出来。
  • 然后kswapd进程将一些脏页写到交换空间(so),这个也可以通过虚存使用(swpd)的增长看出来。

5.7 结论

虚存的性能监控,一般包括以下几点:

  • 大缺页越少,响应时间就更快。因为此时系统在使用内存而不是磁盘。
  • 空闲内存较低是一个好的现象,表明了缓存正被高效使用,除非同时伴有持续的写交换分区的操作。
  • 如果一个系统持续在操作交换分区,表明这个系统内存告紧。

译注

  • 内存写到文件系统:比如在释放内存作为buffer使用的部分,需要将内存内容写到文件系统;内存写到交换分区:比如将实存置换到虚存的时候。
  • 原文中的memory paging指的应该不是内存分页机制,根据上下文指的应该是内存到磁盘的同步,译文中翻译为内存同步
  • 和文件系统相关的内存页,可能是内存中的buffer或cache部分。内存映射到swap file的部分,不确定是和文件系统相关还是和交换分区相关
  • kswapd和pdflush的异同和关联:

    相同点:两者都会把内存数据写到磁盘上
    不同点:两者把内存数据写到磁盘的目的不同:kswapd是为了释放内存,但释放内存前需要先把这部分数据暂存到磁盘上;pdflush是为了同步内存和磁盘的数据。
    关联:正如5.2提到的,pdflush操作会提高kswapd的效率。

  • dirty page,一般翻译为脏页,是指缓存比对应的磁盘内容要新的内存页。

  • 原文这里对于的buffer和cache的解释,和很多资料查到的不一致,个人觉得原文这里的解释有点不妥。

    buffer:内存用于缓存磁盘块以及文件元数据的部分,这部分数据可以通过块设备和块号直接访问
    cache:内存用于缓存文件数据的部分,主要通过inode访问