首页 > 运维 > linux内存回收之drop cache
2021
11-15

linux内存回收之drop cache

Linux有自己完备的一套内存回收机制,并不需要人为的干预,但它同时也提供了一种手动释放的手段,可以让我们在调试的时候使用,方法是通过设置"/proc/sys/vm/drop_cache"参数。

这个参数可接收3个数字的输入,分别是1, 2和3,写入1代表只释放page cache的可回收部分,写入2代表只释放slab cache中的可回收部分。可回收的slab cache是指在调用"kmem_cache_create"函数向slab分配器申请内存时,使用了"SLAB_RECLAIM_ACCOUNT"标志位,主要就是dentry cache和inode cache。

写入3代表同时释放page cache和reclaimable slab cache。很好记,1+2=3嘛,事实上,1就是二级制的01,2就是二进制的10,运行drop cache就是靠这两个置1的bit判断的。具体的实现函数是"drop_caches_sysctl_handler"(代码位于/fs/drop_caches.c):

int drop_caches_sysctl_handler(...){
    if (sysctl_drop_caches & 1) {
	iterate_supers(drop_pagecache_sb, NULL);
	count_vm_event(DROP_PAGECACHE);
    }
    if (sysctl_drop_caches & 2) {
        drop_slab();
	count_vm_event(DROP_SLAB);
    }
    ...}

写入后只会执行一次,后续不用再去管它,不需要写入0去清除什么的(其实你写入0也是不会成功的),如果非强迫症犯了想把它清掉,那就写入4好了,4是"100",末尾两位是0就行。

【page cache的释放

在执行"echo 1 > /proc/sys/vm/drop_caches"命令之前和之后,分别查看"meminfo"中page cache的数量:

grep file /proc/meminfo 
Active(file):    1482380 kB
Inactive(file):   527092 kB

echo 1 > /proc/sys/vm/drop_caches 

grep file /proc/meminfo
Active(file):      48572 kB
Inactive(file):    17872 kB

可见,page cache所占用的内存明显减少,但并没有完全清空。因为这种方式只能清空page cache中"clean"的部分,也就是已经和外部磁盘同步过的部分。

因为"clean"的部分回收起来最简单,既然已经同步过了,直接丢弃即可,下次要用再从磁盘上拷贝回来就可以了,而"dirty"的部分需要先writeback到磁盘,才能释放。所以,"drop cache"准确地应该叫drop clean cache(如果想释放"dirty"的page cache,可以先使用"sync"命令强制同步一下)。


【slab cache的释放

page cache对应的是文件系统中的文件数据(userdata),而inode cache对应的是文件系统中文件的控制结构(metadata)。对于磁盘文件系统,内存inode存在后备存储,因此同page cache一样,较易在内存中重建,释放的代价较低。dentry虽然在磁盘上没有直接对应的结构,但也可根据文件系统中目录inode的信息进行重建。

还是和之前page cache的实验一样,在执行"echo 2 > /proc/sys/vm/drop_caches"命令之前和之后,分别查看"meminfo"中slab cache的大小。

grep -A2 Slab /proc/meminfo 
Slab:            2329432 kB
SReclaimable:    2257644 kB
SUnreclaim:        71788 kB

echo 2 > /proc/sys/vm/drop_caches 

grep -A2 Slab /proc/meminfo  
Slab:             113596 kB
SReclaimable:      64380 kB
SUnreclaim:        49216 kB

代表slab cache中可回收部分的"SReclaimable"明显减少,而代表不可回收部分的"SUnreclaim"的值基本没有变化。

再来看下回收前后dentry cache的数量变化,可见,处于"unused"状态的dcache被回收了 330984 - 6977 个

cat /proc/sys/fs/dentry-state 
337552  330984  45      0       0       0

echo 2 > /proc/sys/vm/drop_caches 

cat /proc/sys/fs/dentry-state      
13440   6977    45      0       0       0


而inode cache的数量,减少了410798-395270个:

cat /proc/sys/fs/inode-state 
410798  1       0       0       0       0       0

echo 2 > /proc/sys/vm/drop_caches 

[root@dev yangcunfeng]# cat /proc/sys/fs/inode-state      
395270  385875  0       0       0       0       0

一个内存inode被一个或多个dentry指向,如果指向一个inode的dentry都被释放,那么该inode也就没有继续存在于内存的意义,也会被同步释放,且由于这种指向关系,释放的inode object总数应略小于释放的dentry object的总数。

借助crash工具的"struct"命令,可以快速得知一个结构体的大小,以笔者使用的"4.18.0-80.el8.x86_64"内核版本为例,dentry和inode的结构体大小分别是208字节和648字节,计算一下,差不多就等于"SReclaimable"中减少的部分。


【小结

清除page cache和slab cache可以快速释放内存,cache虽然占据了内存空间,但其本来就是为了提高性能而存在的,在手动清除后的一段时间里,系统的整体运行效率将受到影响。如果发现即便负责自动回收的kswapd频繁启动,系统的内存资源依然吃紧,应尝试去寻找部分内存始终不能有效释放的原因,手动清除并不能解决根本问题。


参考:LWN - Slab reclaim



本文》有 0 条评论

留下一个回复