/proc/sys/vm/drop_caches 清理缓存
1. 概述
Linux内核为了提高文件访问速度和效率,在内存中保留了一个页面缓存(Page Cache)。当你访问一个文件时,Linux首先会检查页面缓存是否有该文件的副本。如果有,则直接从内存中读取;如果没有,则从硬盘读取并将其添加到页面缓存区以备后用。
然而,在某些情况下,可能希望释放这些占用大量物理内存以避免OOM(Out of Memory)的产生。此时就需要使用 drop_caches 命令了。它是通过向 /proc/sys/vm/drop_caches(实现文件 fs/drop_caches.c,默认是0) 写入特定值来清除不同类型的页式和slab式对象:
# echo 1 > /proc/sys/vm/drop_caches; //清除页式对象; # echo 2 > /proc/sys/vm/drop_caches; //清除slab对象(dentries 和 inodes); # echo 3 > /proc/sys/vm/drop_caches; //同时清理页式对象和slab对象。
虽然 drop_caches 能够清理缓存,但是它并不会影响到系统的正常运行。因为当系统再次需要这些数据时,它会自动从硬盘中读取。但是,在清理缓存后可能会暂时降低系统性能(因为硬盘读取速度慢于内存),出现大量卡I/O的状态,所以在使用drop_caches之前一定要考虑清楚。
另外,在执行 drop_cache 操作后,请务必记得检查是否有足够的磁盘空间来容纳新生成的数据和文件。如果磁盘空间不足,则可能导致新生成的文件无法保存。
直接echo只能清空page cache中"clean"的部分,也就是已经和外部磁盘同步过的部分。因为"clean"的部分回收起来最简单,既然已经同步过了,直接丢弃即可,下次要用再从磁盘上拷贝回来就可以了,而"dirty"的部分需要先writeback到磁盘,才能释放。所以,"drop cache"准确地应该叫drop clean cache(如果想释放"dirty"的page cache,可以先使用"sync"命令强制同步一下)。
与实现自动回收的 kswapd 线程通过扫描LRU链表不同,手动回收page cache是遍历各个文件系统的各个文件,来寻找可供回收的clean pages。
page cache对应的是文件系统中的文件数据(userdata),而inode cache对应的是文件系统中文件的控制结构(metadata)。对于磁盘文件系统,内存inode存在后备存储,因此同page cache一样,较易在内存中重建,释放的代价较低。dentry虽然在磁盘上没有直接对应的结构,但也可根据文件系统中目录inode的信息进行重建。
echo 2前后可以看dentry的状态:
cat /proc/sys/fs/dentry-state cat /proc/sys/fs/inode-state
一个内存inode被一个或多个dentry指向,如果指向一个inode的dentry都被释放,那么该inode也就没有继续存在于内存的意义,也会被同步释放,且由于这种指向关系,释放的inode object总数应略小于释放的dentry object的总数。
借助crash工具的"struct"命令,可以快速得知一个结构体的大小,以笔者使用的"4.18.0-80.el8.x86_64"内核版本为例,dentry和inode的结构体大小分别是208字节和648字节,计算一下,差不多就等于"SReclaimable"中减少的部分。
从dcache和icache的LRU链表获取可回收的数量后,还可以通过"/proc/sys/vm/vfs_cache_pressure"参数来调节slab cache的「回收倾向」。该参数的值越小,则回收slab cache的比例也就越低,当值为0时,即使内存资源紧张也不回收slab cache(非常类似于调节anonymous page和page cache回收比例的"swappiness"参数)。
注意:使用之前需要先sync,将缓存刷到磁盘中。此操作需要root权限,因此在执行这些命令时可能需要使用sudo。
2. 实验
单位:MB # free -m total used free shared buff/cache available Mem: 1825 381 1363 8 79 1413 Swap: 0 0 0 # cp /etc/* /mytest/ # free -m total used free shared buff/cache available Mem: 1825 382 1341 8 101 1412 Swap: 0 0 0 过一段时间: # free -m total used free shared buff/cache available Mem: 1825 382 1341 8 101 1412 Swap: 0 # cat /proc/sys/vm/drop_caches 0 # sync # echo 3 > /proc/sys/vm/drop_caches # free -m total used free shared buff/cache available Mem: 1825 382 1405 8 37 1413 Swap:
echo 2 之后,/proc/meminfo 中的可回收部分 SReclaimable 字段的值也会明显降低。
3. 写个脚本做这个事情
# cat cleanup_cache.sh #!/bin/sh # drop_caches for every 5 mins drop_caches() { echo "Drop caches." sync echo 3 > /proc/sys/vm/drop_caches & return 0 } while true; do sleep 300 drop_caches done exit 0
4. 小结
清除page cache和slab cache可以快速释放内存,cache虽然占据了内存空间,但其本来就是为了提高性能而存在的,在手动清除后的一段时间里,系统的整体运行效率将受到影响。如果发现即便负责自动回收的kswapd频繁启动,系统的内存资源依然吃紧,应尝试去寻找部分内存始终不能有效释放的原因,手动清除并不能解决根本问题。
笔者在工作中就曾经遇到过这样的案例:
kswapd由于持续运行,导致占据了大量的CPU资源,后来发现root cause是有进程一直再往tmpfs里面打印log,而tmpfs属于shmem,在性质上是anonymous pages,内存回收时应该被swap out到外部的swap space。
但系统没有在外部flash设置swap分区,手动drop cache只能回收page cache和slab cache,对anony page是没有用的。tmpfs里的内容不断增加,导致空闲内存低于low watermark,触发kswapd,但没有swap分区,kswapd怎么使劲也是无能为力的,最终的结果就是内存占用率和CPU占用率都很高,系统可能就挂掉了。
参考:
Linux内存回收之drop cache:https://zhuanlan.zhihu.com/p/93962657
posted on 2018-12-08 16:12 Hello-World3 阅读(9194) 评论(0) 编辑 收藏 举报