怎么理解内存中的Buffer和Cache

本文深入探讨了Linux内存管理中的Buffer和Cache,解释了它们在磁盘读写中的作用。Buffer用于缓存磁盘数据,而Cache则缓存文件内容,两者在读写操作中都有所涉及。通过案例分析,展示了Buffer和Cache如何在I/O过程中动态变化,揭示了它们对系统性能优化的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文是通过学习倪朋飞老师的《Linux性能优化实战》 :怎么理解内存中的Buffer和Cache?


内存和 CPU 的关系非常紧密,而内存管理本身也是很复杂的机制,所以感觉知识很硬核、 很难啃,都是正常的。但还是那句话,初学时不用非得理解所有内容,继续往后学,多理 解相关的概念并配合一定的实践之后,再回头复习往往会容易不少。当然,基本功不容放弃。

我们先看一下系统的内存使用情况,比如下面这个 free 输出界面:

free
             total        used        free      shared  buff/cache   available
Mem:        3871192     1152832     1771464       492      946896     2471884
Swap:       4194300       91904     4102396

显然,这个界面包含了物理内存 Mem 和交换分区 Swap 的具体使用情况,比如总内存、 已用内存、缓存、可用内存等。其中缓存是 Buffer 和 Cache 两部分的总和 。

这里的大部分指标都比较容易理解,但 Buffer 和 Cache 可能不太好区分。从字面上来说,Buffer 是缓冲区,而 Cache 是缓存,两者都是数据在内存中的临时存储。那么,这两种“临时存储”有什么区别吗?

注:接下来的内容,Buffer 和 Cache 我会都用英文来表示,避免跟文中的“缓存”一词混淆。而文中的“缓存”,则通指内存中的临时存储。

free 数据的来源

  • Buffers 是内核缓冲区用到的内存,对应的是 /proc/meminfo 中的 Buffers 值。
  • Cache 是内核页缓存和 Slab 用到的内存,对应的是 /proc/meminfo 中的 Cached 与 SReclaimable 之和。

proc 文件系统

/proc 是 Linux 内核提供的一种特殊文件系统,是用户跟内核交互的接口。比方说,用户可以从 /proc 中查询内核的运行状态和配置选项, 查询进程的运行状态、统计数据等,当然,也可以通过 /proc 来修改内核的配置。

proc 文件系统同时也是很多性能工具的最终数据来源。比如我们刚才看到的 free ,就是通过读取 /proc/meminfo ,得到内存的使用情况。

man proc
 Buffers %lu
        Relatively temporary storage for raw disk blocks that shouldn't get tremendously large (20MB or so)
        
Cached %lu
      In-memory cache for files read from the disk (the page cache).  Doesn't include SwapCached.

SReclaimable %lu (since Linux 2.6.19)
             Part of Slab, that might be reclaimed, such as caches.
SUnreclaim %lu (since Linux 2.6.19)
           Part of Slab, that cannot be reclaimed on memory pressure.

通过文档,我们可以看到:

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

好了,我们终于找到了这三个指标的详细定义。到这里,我们是不是长舒一口气,满意地想着,总算弄明白 Buffer 和 Cache 了。不过,知道这个定义就真的理解了吗?这里我给你 提了两个问题,你先想想能不能回答出来。

第一个问题,Buffer 的文档没有提到这是磁盘读数据还是写数据的缓存,而在很多网络搜索的结果中都会提到 Buffer 只是对将要写入磁盘数据的缓存。那反过来说,它会不会也缓存从磁盘中读取的数据呢?

第二个问题,文档中提到,Cache 是对从文件读取数据的缓存,那么它是不是也会缓存写文件的数据呢?

为了弄明白这两个问题,接下来,我们用几个案例来展示, Buffer 和 Cache 在不同场景下的使用情况。

案例

预先安装 sysstat 包,如 yum install sysstat。

之所以要安装 sysstat ,是因为我们要用到 vmstat ,来观察 Buffer 和 Cache 的变化情 况。虽然从 /proc/meminfo 里也可以读到相同的结果,但毕竟还是 vmstat 的结果更加直观。

另外,这几个案例使用了 dd 来模拟磁盘和文件的 I/O,所以我们也需要观测 I/O 的变化情况。

工具安装完成后,你可以打开两个终端,连接到机器上。

场景 1:磁盘和文件写案例

我们先来模拟第一个场景。首先,在第一个终端,运行下面这个 vmstat 命令:

vmstat 1
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  91904 1758276  948  954012    0    0     0     6    0    1   19 16 65  0  0
 0  0  91904 1777896  948  954052    0    0     0     0  1328  2310  0  1 99  0  0

输出界面里, 内存部分的 buff 和 cache ,以及 io 部分的 bi 和 bo 就是我们要关注的重点。

  • buff 和 cache 就是我们前面看到的 Buffers 和 Cache,单位是 KB。
  • bi 和 bo 则分别表示块设备读取和写入的大小,单位为块 / 秒。因为 Linux 中块的大小 是 1KB,所以这个单位也就等价于 KB/s。

正常情况下,空闲系统中,你应该看到的是,这几个值在多次结果中一直保持不变。

接下来,到第二个终端执行 dd 命令,通过读取随机设备,生成一个 500MB 大小的文件:

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

然后再回到第一个终端,观察 Buffer 和 Cache 的变化情况:

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  9 177664  86024      0 2754656    0   32  9920    32 2973 3202  0 22 21 57  0
 2  2 251136 110632      0 2817868  924  460   924 88524 5267 3253  0 26 34 39  0
 2  0 249600 106332      0 2833680 1184  788  1184 123668 4950 2959  0 27 29 44  0
 1  3 250624 108604      0 2830612    0 1020    12 154624 5001 2733  1 27 45 28  0
 0  4 251904 127880      0 2829716   28 1260 14684 179444 3532 2630  1 23 28 49  0
 1  1 251904 104864      0 2820744    0   44 10984 32812 3803 3811  5 19 18 58  0

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

再进一步观察 I/O 的情况,我们会看到:

  • 在 Cache 刚开始增长时,块设备 I/O 很少,bi 只出现了一次 924 KB/s,bo 则只有一 次 32KB。而过一段时间后,才会出现大量的块设备写,比如 bo 变成了 179444
  • 当 dd 命令结束后,Cache 不再增长,但块设备写还会持续一段时间,并且,多次 I/O 写的结果加起来,才是 dd 要写的 500M 的数据。

虽然文档提供了对 Buffer 和 Cache 的说明,但是仍不能覆盖到所 有的细节。比如说,今天我们了解到的这两点:

  1. Buffer 既可以用作“将要写入磁盘数据的缓存”,也可以用作“从磁盘读取数据的缓 存”。
  2. Cache 既可以用作“从文件读取数据的页缓存”,也可以用作“写文件的页缓存”。

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

总结

我们一起探索了内存性能中 Buffer 和 Cache 的详细含义。Buffer 和 Cache 分别缓 存磁盘和文件系统的读写数据。

  • 从写的角度来说,不仅可以优化磁盘和文件的写入,对应用程序也有好处,应用程序可以在数据真正落盘前,就返回去做其他工作。
  • 从读的角度来说,既可以加速读取那些需要频繁访问的数据,也降低了频繁 I/O 对磁盘的压力。

除了探索的内容本身,这个探索过程对你应该也有所启发。在排查性能问题时,由于各种资源的性能指标太多,我们不可能记住所有指标的详细含义。那么,准确高效的手段—— 查文档,就非常重要了。

所以我们一定要养成查文档的习惯,并学会解读这些性能指标的详细含义。此外,proc 文件系统也是我们的好帮手。它为我们呈现了系统内部的运行状态,同时也是很多性能工具的数据来源,是辅助排查性能问题的好方法。

欢迎扫码关注V信公众号一起交流:一苦四甜

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值