Page Cache

在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,感觉是内存不够用了。其实不然,这是Linux内存管理的一个优秀的特征,主要特点是,物理物理内存有多大,Linux都将其充分利用,将一些程序调用过的硬盘数据读入内存(buffer/Cache),利用内存读写的高速特性来提供Linux系统的数据访问性能高。本章的主要内容学习内容如下:

  • 什么是Page cache(what)
  • 为什么需要page cache(why)
  • Page cache是如何产生和释放的(how)

1. 什么是Page Cache

当程序去读文件,可以通过read也可以通过mmap去读,当你通过任何一种方式从磁盘读取文件时,内核都会给你申请一个Page cache,用来缓存磁盘上的内容。这样读过一次的数据,下次读取的时候就直接从Page cache里去读,提升了系统的整体性能。

Page Cache_第1张图片

对于Linux可以怎么来观察Page Cache呢?其实,在Linux上直接可以通过命令来看,他们的内容是一致的。

首先最简单的是free命令来看一下
在这里插入图片描述

首先我们来看看buffers和cached的定义

  • Buffers 是对原始磁盘块的临时存储,也就是用来缓存磁盘的数据,通常不会特别大(20MB 左右)。这样,内核就可以把分散的写集中起来,统一优化磁盘的写入,比如可以把多次小的写合并成单次大的写等等。
  • Cached 是从磁盘读取文件的页缓存,也就是用来缓存从文件读取的数据。这样,下次访问这些文件数据时,就可以直接从内存中快速获取,而不需要再次访问缓慢的磁盘

buffer cache和page cache在处理上是保持一致的,但是存在概念上的差别,page cache是针对文件的cache,buffer是针对磁盘块数据的cache,仅此而已。

2. 为什么需要page cache

通过上图,我们可以直观的看到,标准的I/O和内存映射会先将数据写到Page Cache,这样做是通过减小I/O次数来提升读写效率。我们来实际的例子,我们先来生成一个1G的文件,然后通过把Page cache清空,确保文件内容不在内存中,一次来比较第一次和第二次读文件的差异。

# 1. 生成一个1G的文件
dd if=/dev/zero of=/home/dd.out bs=4096 count=1048576
# 2.第一次读取文件的耗时如下:
root@root-PC:~# time cat /home/dd.out &> /dev/null
real    0m1.109s
user    0m0.016s
sys     0m1.093s
#  23.清空Page Cache,先执行一下sync来将脏页同步到磁盘,在执行drop cache
sync && echo 3 > /proc/sys/vm/drop_caches
# 4. 第二次读取文件的耗时如下:
    root@root-PC:~# time cat /home/dd.out &> /dev/null
real    0m36.018s
user    0m0.069s
sys     0m4.839s

通过这两次详细的过程,可以看出第一次读取文件的耗时远小于第二次耗时

  • 因为第一次读取的时候,由于文件内容已经在生成文件的时候已经存在,所以直接从内存读取的数据
  • 第二次会将缓存数据清掉,会从磁盘上读取内容,磁盘I/O比较耗时,内存相比磁盘会快很多

所以Page Cache存在的意义,减小I/O,提升应用的I/O速度。对于Page Cache方案,我们采用原则如下

  • 如果不想增加应用的复杂度,我们优先使用内核管理的Page Cache
  • 如果应用程序需要做精确控制,就需要不走Cache,因为Page Cache有它自身的局限性,就是对于应用程序太过于透明了,以至于很难有好的控制方法。

3. Page Cache是如何“诞生的”

Page Cache的产生有两种不同的方式

  • Buffered I/O(标准I/O)
  • Memory-Mapped I/O(储存映射IO)

这两种方式分别都是如何产生Page Cache的呢?
Page Cache_第2张图片

从图中可以看到,二者是都能产生Page Cache,但是二者还是有差异的

  • 标准I/O是写的话用户缓存区(User page对应的内存),然后再将用户缓存区里的数据拷贝到内核缓存区(Pagecahe Page对应的内存);如果是读的话则是内核缓存区拷贝到用户缓存区,再从用户缓存区去读数据,也就是Buffer和文件内容不存在映射关系
  • 储存映射IO,则是直接将Page Cache的Page给映射到用户空间,用户直接读写PageCache Page里的数据

从原理来说储存映射I/O要比标准的I/O效率高一些,少了“用户空间到内核空间互相拷贝”的过程。下图是一张简图描述这个过程:

Page Cache_第3张图片

  • 首先,往用户缓冲区Buffer(用户空间)写入数据,然后,Buffer中的数据拷贝到内核的缓冲区(这个是PageCache Page)
  • 如果内核缓冲区还没有这个page,就会发生Page Fault会去分配一个Page;如果有,就直接用这个PageCache的Page
  • 拷贝结束后,该PageCache的Page是一个Dirty Page脏页,然后该Dirty Page中的内容会同步到磁盘,同步到磁盘后,该PageCache Page变味Clean Page并且继续存在系统中

我们可以通过手段来测试脏页,如下图所示

$ cat /proc/vmstat | egrep "dirty|writeback"
nr_dirty 44
nr_writeback 0
nr_writeback_temp 0
nr_dirty_threshold 1538253
nr_dirty_background_threshold 768187
  • nr_dirty:表示系统中积压了多少脏页(单位为Page 4KB)
  • nr_writeback则表示有多少脏页正在回写到磁盘中(单位为Page 4KB)

总结

读过程,当内核发起一个读请求时候

  • 先检查请求的数据是否缓存到page Cache中,如果有则直接从内存中读取,不访问磁盘
  • 如果Cache中没有请求数据,就必须从磁盘中读取数据,然后内核将数据缓存到Cache中
  • 这样后续请求就可以命中cache,page可以只缓存一个文件的部分内容,不需要把整个文件都缓存

写过程,当内核发起一个写请求时候

  • 直接写到Cache中,内核会将被写入的Page标记为dirty,并将其加入到dirty list中
  • 内核会周期性的将dirty list中的page回写到磁盘上,从而使磁盘上的数据和内存中缓存的数据一致

3. page cache是如何“死亡”

free命令中的buffer/cache中的是“活着”的Page Cache,那他们是什么时候被回收的呢?

Page Cache_第4张图片

回收的主要方式有两种

  • 直接回收:
  • 后台回收:

观察Page cache直接回收和后台回收最简单方便的方式,借助这个工具,可以明确观察内存回收行为

Page Cache_第5张图片

  • pgscank/s: kswapd(后台回收线程)每秒扫面的Page个数
  • pgscand/s: Application在内存申请过程中每秒直接扫描的Page个数
  • pgsteal/s: 扫面的page中每秒被回收的个数
  • %vmeff: pgsteal/(pgscank+pgscand),回收效率,越接近100说明系统越安全,越接近0,说明系统内存压力越大
  • pgpgin/s 表示每秒从磁盘或SWAP置换到内存的字节数(KB)
  • pgpgout/s: 表示每秒从内存置换到磁盘或SWAP的字节数(KB)
  • fault/s: 每秒钟系统产生的缺页数,即主缺页与次缺页之和(major + minor)
  • majflt/s: 每秒钟产生的主缺页数.
  • pgfree/s: 每秒被放入空闲队列中的页个数

详细的可参考网页sar工具在监控性能方向的实践

4. 总结

本章的主要内容是学习了什么是page Cache,为什么需要page Cache,Page Cache是如何诞生的以及如何死亡,一下几个重点:

  • Page Cache属于内核,不属于用户
  • Page Cache对于应用提升IO效率而言是一个投入产出比较高的方案,存在是很有必要的
  • Page Cache是在应用程序读写文件的过程中产生,所以在读写文件之前,你需要留意是否还有足够的内存来分配Page Cache
  • Page Cache中的脏页很容易引起问题
  • 在系统内存不足的时候,系统就会回收Page Cache来释放出来内存,可以通过sar或者/proc/vmstat来观察这个行为从而更好的判断问题是否跟回收有关

Page Cache是将磁盘中的数据缓存到内存中,较小磁盘I/O操作,从而提高性能。此外还要确保Page Cache中的数据更改能同步到磁盘上,这称之为Page回写(Page WriteBack)。一个inode对应一个Page cache对象,一个Page Cache对象保护多个物理Page。对磁盘的数据进行缓存,从而提高性能主要基于两个因素:

  • 磁盘访问速度比内存慢几个数量级
  • 访问过的数据,很大概率再次访问(局部性原理)

你可能感兴趣的:(文件系统)