Contents

Linux中的Buffers&Cache

1.理论

Linux free 输出的内存使用里面输出的信息来自:/proc/meminfo

先上官方解释:

man free

1
2
3
4
5
   #buffers
   Memory used by kernel buffers (Buffers in /proc/meminfo)

   #cache  
   Memory used by the page cache and slabs (Cached and SReclaimable in /proc/meminfo)

2.测试:

2.1 文件写入测试

执行以下命令,并启动另外一个终端执行

vmstat 1

1
dd if=/dev/urandom of=/tmp/file bs=1M count=500

通过观察 vmstat 的输出,我们发现,在 dd 命令运行时, Cache 在不停地增长,而 Buffer 基本保持不变。

2.2 磁盘写入测试

注意:需要保证sdb是空白的磁盘

执行以下命令,并启动另外一个终端执行

vmstat 1

1
2
3
4
# 首先清理缓存
$ echo 3 > /proc/sys/vm/drop_caches
# 然后运行 dd 命令向磁盘分区 /dev/sdb1 写入 2G 数据
$ dd if=/dev/urandom of=/dev/sdb1 bs=1M count=2048

从这里你会看到,虽然同是写数据,写磁盘跟写文件的现象还是不同的。写磁盘时(也就是 bo 大于 0 时),Buffer 和 Cache 都在增长,但显然 Buffer 的增长快得多。

这说明,写磁盘用到了大量的 Buffer,这跟我们在文档中查到的定义是一样的。

对比两个案例,我们发现,写文件时会用到 Cache 缓存数据,而写磁盘则会用到 Buffer 来缓存数据。所以,回到刚刚的问题,虽然文档上只提到,Cache 是文件读的缓存,但实际上,Cache 也会缓存写文件时的数据。

2.3 文件读取测试

执行以下命令,并启动另外一个终端执行

vmstat 1

1
2
3
4
# 首先清理缓存
$ echo 3 > /proc/sys/vm/drop_caches
# 运行 dd 命令读取文件数据
$ dd if=/tmp/file of=/dev/null

观察 vmstat 的输出,你会发现读取文件时(也就是 bi 大于 0 时),Buffer 保持不变,而 Cache 则在不停增长。这跟我们查到的定义“Cache 是对文件读的页缓存”是一致的。

2.4 磁盘读取测试

执行以下命令,并启动另外一个终端执行

vmstat 1

1
2
3
4
# 首先清理缓存
$ echo 3 > /proc/sys/vm/drop_caches
# 运行 dd 命令读取文件
$ dd if=/dev/sda1 of=/dev/null bs=1M count=1024

观察 vmstat 的输出,你会发现读磁盘时(也就是 bi 大于 0 时),Buffer 和 Cache 都在增长,但显然 Buffer 的增长快很多。这说明读磁盘时,数据缓存到了 Buffer 中。

3.总结

Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。

Buffers 和 Cache 可以极大提升系统的 I/O 性能。通常,我们用缓存命中率,来衡量缓存的使用效率。命中率越高,表示缓存被利用得越充分,应用程序的性能也就越好。

你可以用 cachestat 和 cachetop 这两个工具,观察系统和进程的缓存命中情况。其中,

  • cachestat 提供了整个系统缓存的读写命中情况。
  • cachetop 提供了每个进程的缓存命中情况。

不过要注意,Buffers 和 Cache 都是操作系统来管理的,应用程序并不能直接控制这些缓存的内容和生命周期。所以,在应用程序开发中,一般要用专门的缓存组件,来进一步提升性能。

比如,程序内部可以使用堆或者栈明确声明内存空间,来存储需要缓存的数据。再或者,使用 Redis 这类外部缓存服务,优化数据的访问效率。

4.补充

内存泄露工具memleak 进行排查。