内存回收

这里的内存回收并不是指的任意语言中的 GC,而是指操作系统在内存不够的时候的一种保护行为。

其实就是释放掉可以回收的内存。

那么操作系统如何知道什么内存可以被回收呢?

文件页

缓存和缓冲区的数据,由于都是可以再从磁盘中读取的,所以可以回收,称为文件页。

大部分文件页都是可以被直接回收的,但是如果被应用程序修改过的话那么就必须先写磁盘才能被回收了,称为脏页。

  • 可以在应用程序中,通过系统调用 fsync ,把脏页同步到磁盘中;
  • 也可以交给系统,由内核线程 pdflush 负责这些脏页的刷新。

这部分的回收称为:直接内存回收

swap

实在没办法了,其实也可以回收程序动态分配的堆内存,称为匿名页。

这就是 linux 的 swap 干的,将一些内存数据先写到磁盘中,等需要的时候再重新从磁盘读取到内存中使用。

kswapd0(k swap d0)

除了直接内存回收,还有一个专门的内核线程用来定期回收内存,也就是kswapd0。为了衡量内存的使用情况,kswapd0 定义了三个内存阈值(watermark,也称为水位),分别是

页最小阈值(pages_min)、页低阈值(pages_low)和页高阈值(pages_high)。剩余内存,则使用 pages_free 表示。

image.png

kswapd0 定期扫描内存的使用情况,并根据剩余内存落在这三个阈值的空间位置,进行内存的回收操作。

  • 剩余内存小于页最小阈值,说明进程可用内存都耗尽了,只有内核才可以分配内存。
  • 剩余内存落在页最小阈值页低阈值中间,说明内存压力比较大,剩余内存不多了。这时 kswapd0 会执行内存回收,直到剩余内存大于高阈值为止。
  • 剩余内存落在页低阈值页高阈值中间,说明内存有一定压力,但还可以满足新内存请求。
  • 剩余内存大于页高阈值,说明剩余内存比较多,没有内存压力。

swappiness

  • 对文件页的回收,当然就是直接回收缓存,或者把脏页写回磁盘后再回收。
  • 而对匿名页的回收,其实就是通过 Swap 机制,把它们写入磁盘后再释放内存。

关闭 swap

swapoff -a