内存回收的方式
直接回收:发生内存分配,而此时的剩余空闲内存不足时,会执行立即内存回收。
定期回收:专门的内核线程kswapd0定期回收内存。
Linux 内存回收的具体方法
- 页缓存:通过LRU算法回收文件页缓存。包括cache、buffer,通过内存映射的文件映射页。
- 通过换出守护进程(kswapd)执行换页,它找出最近不使用的页加入到空闲链表,其中包括应用程序内存。页面换出涉及写入文件系统或者一个交换设备,仅在配置了交换文件或设备时才可用。
- OOM(Out of Memory)机制:内存耗尽终结者搜索并杀死可牺牲的进程以释放内存。
- 手动回收:通过修改/proc/sys/vm/drop_caches的值进行手动回收,最好再执行下sync命令回写脏页
0:释放pagecache(即文件页) 1:释放目录缓存和inodes 3:释放pagecache(即文件页)、目录缓存和inodes
内核线程定期回收
kswapd0 扫描非活动和活动内存的LRU(最近最少被使用)页列表以释放页面。定义了三个内存阈值(watermark,也称为水位)
- 最小页面阈值(pages_min)
- 低页面阈值(pages_low)
- 高页面阈值(pages_high)
剩余内存小于最小页面阈值:说明进程可用内存都耗尽了,只有内核才可以分配内存。
剩余内存 在最小页面阈值-低页面阈值之间: 说明内存压力比较大,剩余内存不多。这时 kswapd0 会执行内存回收,直到剩余内存大于高阈值为止。
剩余内存 在低页面阈值-高页面阈值之间:说明内存有一定压力,但还可以满足新内存请求。
剩余内存大于高页面阈值:说明剩余内存比较多,没有内存压力。
最低阈值是可调的(vm.min_free_kbytes),并且其他阈值基于它按比例放大。pages_low = pages_min5/4、pages_high = pages_min3/2
页缓存的活动页和非活动页都分别设置有列表,这些列表按照LRU方式工作,因此kswapd能快速找到空闲页。
kswapd先扫描非活动列表,然后按需扫描活动列表。
术语"扫描"指遍历列表检查页面:如果页被锁定或者是脏的,它可能不适合释放。
活跃和非活跃的内存页,按照类型的不同,又分别分为文件页和匿名页,对应着缓存回收和 Swap 回收。
$ cat /proc/meminfo | grep -i active | sort
Active(anon): 167976 kB
Active(file): 971488 kB
Active: 1139464 kB
Inactive(anon): 720 kB
Inactive(file): 2109536 kB
Inactive: 2110256 kB
参考链接:https://blog.systemd.cn/2019/Linux%E5%86%85%E5%AD%98%E5%9B%9E%E6%94%B6%E4%B8%8Eswap.html
参考链接:https://segmentfault.com/a/1190000021036015
参考书籍:《性能之巅 洞悉系统、企业与云计算》