说明
- 为了加快高速设备访问低速设备的访问速度,Linux通过缓存的方式实现高速设备对低速设备上数据的映射访问,以减少低速设备的访问次数,提高平均访问速度。
常见场景
CPU/内存
- CPU速度远远大于内存读取速度,为了加快内存的访问速度,CPU硬件上存在一级缓存,二级缓存,甚至三级缓存,读写速度快于内存访问,缓存部分读写频繁的内存数据,也叫做CPU Cache。
内存/硬盘
- 内存读写速度远远快于硬盘,如果每次读写都去直接操作磁盘,一方面操作速度会被限制,一方面也会降低磁盘使用寿命,因此不管是对磁盘的读操作还是写操作,操作系统都会将数据缓存起来。
- 内存缓存很重要,如果每次都直接操作磁盘,很容易将磁盘写坏,例如:循环录像。
内存缓存分类
- 文件读写的buffer和Cache,由于虚拟内存是通过页的形式管理的,而buffer和Cache也是以内存页为单位,因此也叫做Page Cache。
- 虚拟文件系统VFS的目录项(Dentry)和索引结点(Inode)数据。
- 交换空间swap的swap Cache。
- …
buffer和Cache
- Page Cache根据文件操作是读还是写分为两类:buffer(缓冲区)和cache(缓存区)。
- 由中文命名可知它们的用途,缓冲区重点在于冲是防止写入大量数据对硬盘造成冲击,因此是写数据时作为缓冲,而缓存区重点在于存是用于数据备份和缓存命中,因此是读数据时作为缓存。
- buffer和Cache的大小可以通过free命令或者/proc/meminfo查看。
xxx@chejiser:~$ free -m
total used free shared buffers cached
Mem: 128922 125157 3764 25 20418 79372
-/+ buffers/cache: 25365 103556
Swap: 123977 1121 122856
xxx@chejiser:~$ cat /proc/meminfo
MemTotal: 132016204 kB
MemFree: 3857000 kB
MemAvailable: 129307976 kB
Buffers: 20908916 kB //buffer大小
Cached: 81277832 kB //Cache大小
...
理解
- 所有的文件IO(包括网络文件)都是直接和内存页缓存交互,操作系统通过一系列机制,实现文件访问到内存页访问的映射,很大一部分程度上,文件读写的优化就是对页缓存使用的优化。
Dentry和Inode
- 内存中不仅仅缓存了磁盘读写的Page Cache,也缓存了文件读写时必要的信息:虚拟文件系统中的目录项(Dentry)和索引结点(Inode)。
- 内存占用查看如下:
* Dentry和Inode保存在内核Slab中,可通过meminfo查看Slab内存占用
xxx@chejiser:~$ cat /proc/meminfo
....
Slab: 3964 kB //slab 内存占用
SReclaimable: 1320 kB //可回收slab占用
....
* 再查看Dentry和Inode占用
xxx@chejiser:~$ slabtop //slabtop是通过/proc/slabinfo获取的信息
...
xxx@chejiser:~$ cat /proc/slabinfo
slabinfo - version: 2.1
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
dentry 2880 2880 128 32 1 : tunables 0 0 0 : slabdata 90 90 0
.....
swap Cache
- 交换空间也是内存和磁盘之间进行数据交换,也有缓存,可通过meminfo查看。
xxx@chejiser:~$ cat /proc/meminfo
MemTotal: 132016204 kB
MemFree: 3857000 kB
MemAvailable: 129307976 kB
Buffers: 20908916 kB
Cached: 81277832 kB
SwapCached: 65580 kB //SwapCached大小
....
内存缓存回收
- 系统会自动按照一定规则对缓存进行回收,也可以手动回收。
- 系统接口如下:
/proc/sys/vm/drop_caches
echo 0 > /proc/sys/vm/drop_caches //不释放(系统默认值)
echo 1 > /proc/sys/vm/drop_caches //仅清除PageCache(buffer和Cache)
echo 2 > /proc/sys/vm/drop_caches //清除目录项(Dentry)和索引结点(Inode)
echo 3 > /proc/sys/vm/drop_caches //清除PageCache、目录项(Dentry)和索引结点(Inode)
- 清空缓存不会杀死任何应用程序/服务,清理操作并不会释放所有内存,正在使用中的内存页是不会被清理的,操作是安全的,如果应用程序原因也可能导致缓存无法被释放。
- swap cache释放
swapoff -a && swapon -a
- 内存缓存释放前最好 sync下,不然内存页是脏页,系统不会释放,导致释放效果不明显,不执行sync也不会导致数据丢失。