序
本文主要研究一下linux的文件缓存
文件缓存
linux使用page cache来缓存最近读取的文件,也有目录结构(dcache: Directory Entry Cache
)缓存及inode缓存,它们都使用了LRU算法来管理这些page及dentries cache
vmstat
代码语言:javascript复制## vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 5076692 1664208 1032 35263320 0 0 0 4 0 0 0 0 99 0 0
vmstat显示的memory中的cache部分即是文件缓存,单位为kb
free
代码语言:javascript复制free -m
total used free shared buff/cache available
Mem: 64038 27974 1619 3208 34444 32370
Swap: 32127 4957 27170
free命令显示的buff/cache部分包含了buffer memory及swap cache
meminfo
代码语言:javascript复制cat /proc/meminfo | grep ^Cached
Cached: 2942600 kB
/proc/meminfo中的Cached展示了page cache大小
配置
/etc/sysctl.conf包含我们可以在运行时设置的系统范围内的内核参数,sysctl只是临时改动,如果用使得参数变更持久化则需要更改到这个文件。要在不重新启动的情况下应用/etc/sysctl.conf文件中的更改,我们可以使用sysctl的-p开关
代码语言:javascript复制sudo sysctl -p
vm.vfs_cache_pressure
vm.vfs_cache_pressure用来控制内核回收page与dentries(dcache及inode cache)的倾向性。
- 默认值100,即内核自己根据情况将二者在一个合理的比例
- 较低的值(低于100)则使其倾向于回收page cache,来保留dentries cache。
- 较高的值(高于100)会使内核更倾向于回收dentries cache,来保留page cache。
代码语言:javascript复制如下设置则让内核倾向于回收page cache
sudo sysctl -w vm.vfs_cache_pressure=50
vm.swappiness
用于控制使用swap分区的倾向性
- 默认值为60,意味着内核会在RAM使用率达到60%(可用RAM低于40%)时开始使用swap分区
- 较低的值则倾向使用RAM,尽量少使用swap分区,比如0则表示内核在RAM(
Random Access Memory
)严重不足时才使用swap分区,即page cache尽可能得缓存在了RAM - 较高的值则倾向使用swap分区,比如100则表示内核非常积极使用swap分区,即使还有比较多的RAM可用,即page cache更多的是在swap分区
代码语言:javascript复制如下设置则让内核尽可能使用RAM
sudo sysctl -w vm.swappiness=10
vm.dirty相关参数
代码语言:javascript复制sysctl -a | grep dirty
vm.dirty_background_ratio = 10
vm.dirty_background_bytes = 0
vm.dirty_ratio = 20
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500
这些参数用于控制脏数据(已经被修改但是未写入到硬盘)何时写入硬盘 如果我们用_bytes设置vm.的值,则vm._ratio变量将变为0,反之亦然 除了通过sysctl -a,也可以通过cat /proc/sys/vm/dirty_background_ratio这样子来查看
vm.dirty_background_ratio与vm.dirty_background_bytes
用于设置内存中可以存储脏数据的最大数量。例如,如果你的系统有32GB的内存,并且vm.dirty_background_ratio设置为10,那么最多可以有3.2GB的脏数据存储在内存中,超过这个数值后,就会触发脏数据的写入操作;而vm.dirty_background_bytes则是指定了绝对值,单位bytes
代码语言:javascript复制sudo sysctl -w vm.dirty_background_ratio=10
sudo sysctl -w vm.dirty_background_bytes=511870912
vm.dirty_ratio与vm.dirty_bytes
用来设置整个系统可以存储脏数据的最大数量的。例如,如果你的系统有32GB的内存,并且vm.dirty_ratio设置为20,那么最多可以有6.4GB的脏数据存储在整个系统中,超过这个数值后,就会触发脏数据的写入操作;而vm.dirty_bytes则是指定了绝对值,单位bytes;与vm.dirty_background_ratio的区别在于当系统到达此点时,必须将所有脏数据提交到磁盘,同时所有新的I/O块都会被阻塞,直到脏数据被写入磁盘
代码语言:javascript复制sudo sysctl -w vm.dirty_ratio=20
sudo sysctl -w vm.dirty_bytes=511870912
vm.dirty_writeback_centisecs与vm.dirty_expire_centisecs
在断电的情况下,缓存在系统内存中的数据有丢失的风险。因此,为了保护系统免于数据丢失_centisecs系列的参数决定了将数据写入辅助存储的时间和频率。 vm.dirty_expire_centisecs管理数据在写入驱动器之前在缓存中可以存活多长时间。
代码语言:javascript复制如下设置可以在缓存中保留40秒,1s等于100 centisecs,当pdflush/flush/kdmflush在运行的时候,他们会检查是否有数据超过这个时限,如果有则会把它异步地写到磁盘中
sudo sysctl -w vm.dirty_expire_centisecs=4000
vm.dirty_writeback_centisecs是后台进程检查是否有数据要写入辅助存储的频率,即指定多长时间pdflush/flush/kdmflush这些进程会唤醒一次,然后检查是否有缓存需要清理。该值越低,频率越高。
代码语言:javascript复制如下配置为每5秒检查一次缓存
sudo sysctl -w vm.dirty_writeback_centisecs=500
删除cache
我们可以通过往/proc/sys/vm/drop_caches写入指定的值来指定怎么删除cache
删除示例
代码语言:javascript复制# 查看当前的drop_caches值
cat /proc/sys/vm/drop_caches
# 将drop_caches值设置为1,释放页缓存
echo 1 > /proc/sys/vm/drop_caches
# 将drop_caches值设置为2,释放目录项和节点缓存
echo 2 > /proc/sys/vm/drop_caches
# 将drop_caches值设置为3,释放页缓存、目录项和节点缓存
echo 3 > /proc/sys/vm/drop_caches
这是一个非破坏性的操作,并且不会释放脏对象的内存。因此,在进行此操作前,需要先运行sync命令,确保所有未写的系统缓冲区都已经被写入到磁盘中,包括已修改的i节点、已延迟的块I/O和读写映射文件
删除失败
vmtouch可以将文件内容锁定在内存中,因而drop cache可能没有效果,比如
代码语言:javascript复制vmtouch -tl test.dat
LOCKED 492712 pages (1G)
cat /proc/meminfo | grep ^Cached &&
sudo bash -c 'sync; echo 3 > /proc/sys/vm/drop_caches' &&
cat /proc/meminfo | grep ^Cached
Cached: 3336092 kB
Cached: 3169224 kB
代码语言:javascript复制可以看到这里无法释放锁定的cache,可以通过memlock来限定每个进程最大锁定的大小(
/etc/security/limits.conf
)配置
* hard memlock unlimited
* soft memlock unlimited
代码语言:javascript复制查看
ulimit -Ha | grep locked
max locked memory (kbytes, -l) 2033684
小结
linux使用page cache来缓存最近读取的文件,也有目录结构(dcacheDirectory Entry Cache
)缓存及inode缓存,它们都使用了LRU算法来管理这些page及dentries cache
- 可以通过vmstat、free、/proc/meminfo来查看
- 可以通过vm.vfs_cache_pressure、vm.swappiness、vm.dirty_*来配置
- 可以通过设置/proc/sys/vm/drop_caches的值来进行删除
doc
- How to Configure File System Caching in Linux
- Dropping Page Cache in Linux
- Restrict Size of the Buffer Cache in Linux