本文是通过学习倪朋飞老师的《Linux性能优化实战》 :怎么理解内存中的Buffer和Cache?
怎么理解内存中的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 的说明,但是仍不能覆盖到所 有的细节。比如说,今天我们了解到的这两点:
- Buffer 既可以用作“将要写入磁盘数据的缓存”,也可以用作“从磁盘读取数据的缓 存”。
- Cache 既可以用作“从文件读取数据的页缓存”,也可以用作“写文件的页缓存”。
简单来说,Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读 请求中,也会用在写请求中。
总结
我们一起探索了内存性能中 Buffer 和 Cache 的详细含义。Buffer 和 Cache 分别缓 存磁盘和文件系统的读写数据。
- 从写的角度来说,不仅可以优化磁盘和文件的写入,对应用程序也有好处,应用程序可以在数据真正落盘前,就返回去做其他工作。
- 从读的角度来说,既可以加速读取那些需要频繁访问的数据,也降低了频繁 I/O 对磁盘的压力。
除了探索的内容本身,这个探索过程对你应该也有所启发。在排查性能问题时,由于各种资源的性能指标太多,我们不可能记住所有指标的详细含义。那么,准确高效的手段—— 查文档,就非常重要了。
所以我们一定要养成查文档的习惯,并学会解读这些性能指标的详细含义。此外,proc 文件系统也是我们的好帮手。它为我们呈现了系统内部的运行状态,同时也是很多性能工具的数据来源,是辅助排查性能问题的好方法。