一、常见与Page Cache有关场景
- 服务器的load飙高
- 服务器的I/O吞吐飙高
- 业务响应时延出现大的毛刺
- 业务平均访问时延明显增加
二、什么是Page Cache?
1、观察Page Cache方式
- /proc/vmstat
- /proc/meminfo
- free
1.1、/proc/meminfo
- 含义
- 查看 Kernel Documentation中meminfo这一节
- 代码分析
cat /pro/meminfo
...
Buffers: 1224 kB
Cached: 111472 kB
SwapCached: 36364 kB
Active: 6224232 kB
Inactive: 979432 kB
Active(anon): 6173036 kB
Inactive(anon): 927932 kB
Active(file): 51196 kB
Inactive(file): 51500 kB
...
Shmem: 10000 kB
...
SReclaimable: 43532 kB
...
* **Buffers + Cached + SwapCached = Active(file) + Inactive(file) + Shmem + SwapCached**
* 等式右边这些项目把Buffers和Cached细分了,分成了Active(file)、Inactive(file)和Shmem
* Buffers更加依赖于内核实现,在不同内核版本中含义可能不一致
* 等式右边和应用程序的关系更加直接
* **Active(file)+Inactive(file)**
* File-backed page(与文件对应的内存页)
* mmap()内存映射方式和buffered I/O来消耗的内存就属于这部分
* 实际生产环境最容易产生问题
* **SwapCached**
* 是打开了swap后,把Inactive(anon)+Active(anon)这两项里匿名页(比如进程的堆、栈等,没有一个文件作为back store)给交换磁盘(swap out),然后再读入到内存(swap in)后分配的内存
* 读入到内存后原来的Swap File还在,所以SwapCached也可以认为是File-bcached page,即属于Page Cache
* 目的:减少I/O
* SwapCached产生过程
![](https://s4.51cto.com/images/blog/202009/17/1cf614cb45453dc5fcb9ea624f5c1995.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
* SwapCache只在Swap分区打开情况下才会有,Swap过程产生的I/O会很容易引起抖动
* **Shmem**
* 是指匿名共享映射这种方式分配的内存(free命令中的shared这一项)
* 比如:tmpfs(临时文件系统)
* 此部分生产环境中问题比较少
1.2、free
$ free -k
total used free shared buff/cache available
Mem: 7926580 7277960 492392 10000 156228 430680
Swap: 8224764 380748 7844016
- 通过解析/proc/meminfo统计所得
- 源码:procfs中free.c文件
- buff/cache = Buffers + Cached + SReclaimable
- 强调内存的可回收性
- Sreclaimable是指被回收的内核内存,包括dentry和inode等
- 验证公式:1224+111472+43532=156228
- 注意:数据是动态变化,执行命令本身会带来内存开销,等式未必严格相等。
- buff/cache = Buffers + Cached + SReclaimable
1.3、是否可以不要Page Cache?
- 思路1:应用程序维护自己的Cache做更加细粒度的控制
- 比如:MySQL,参考MySQL Buffer Pool,实现复杂度高,不如内核的Page Cache简单高效
- 思路2:使用Direct I/O绕过Page Cache(见下方分析)
1.4、为什么需要Page Cache?
- 标准I/O、内存映射会先把数据写入到Page Cache
- 目的:介绍I/O次数来提升读写效率
- 案例:
1、生成一个1G大小的新文件
dd if=/dev/zero of=/home/test/dd.out bs=4096 count=((1024*256))
2、把Page Cache清空
echo 3 >/proc/sys/vm/drop_caches
3、确保文件内容不再内存中
4、比较第一次读文件和第二次读文件耗时差异
time cat /home/test/dd.out &> /dev/null
* 分析
* 第二次读取文件的耗时远小于第一次耗时,因为第一次从磁盘来读取的内容,磁盘I/O比较耗时,第二次读取的时候由于文件内容已经在第一次读取到内存了,所以直接从内存读取的数据
* Page Cache存在的意义
* **减少I/O,提升应用的I/O速度**
=================== END ===================