Contents

Linux中限制缓存的大小

1. 概述

在本文中,我们将讨论缓冲区缓存。缓冲区缓存是 Linux 用来加快读取操作速度的内存区域。我们将首先回顾缓冲区缓存的基础知识以及我们需要它的原因。接下来,我们将讨论如何清除它,回收占用的内存。最后,我们将展示如何限制其大小。

2. 缓冲区缓存

每个计算机程序的核心都是读取和写入数据。数据传输的速度因介质而异,极大地影响了整体性能和用户体验的响应时间。出于这个原因,Linux 尝试将这些缓冲区缓存的 I/O 操作数量降至最低。

缓冲区缓存存在于内存中,因此与磁盘相比,读取和写入它们要快得多。出于这个原因,Linux 不是每次都去磁盘,而是对那些缓冲区缓存执行那些写操作。然后它会做一些簿记,以便知道缓存了哪些数据,并安排定期将该数据刷新到实际磁盘上

虽然使用缓冲区高速缓存可以大大提高整体性能,但它们有时会占用主内存的很大一部分。当我们想要回收内存时,这会增加额外的延迟,因此会对正在运行的进程产生负面影响。在以下部分中,我们将研究如何通过手动清除这些缓存并限制它们可以占用的最大大小来减轻这种副作用。

3. 如何清除缓冲区缓存

想象一下,我们打算启动一个需要我们机器上大部分可用物理内存的进程。根据我们在上一节中讨论的内容,Linux 必须将缓冲区高速缓存刷新到磁盘上以回收此内存。然而,这需要时间,因此可能会导致严重的延误。为了解决这个问题,我们可以主动刷新这些缓存。

为此,**我们需要写入procfs 中的 drop_caches 文件。**让我们看看如何做到这一点:

$ echo 3 > /proc/sys/vm/drop_caches 

请注意,procfs中的**drop_caches文件允许我们选择要刷新的缓冲区缓存文件类型

4. 如何限制Buffer Cache的大小

在上一节中,我们看到了如何清除缓冲区缓存。虽然这样做可以完成工作,但每次都需要手动操作。更好的方法是首先**防止缓冲区高速缓存增长。**在接下来的两节中,我们将展示两种不同的方法。

4.1. 增加vm.vfs_cache_pressure的值

我们可以告诉 Linux 更积极地取回它用来缓存一些虚拟文件系统对象的内存。更具体地说,我们可以增加** /proc/sys/vm/vfs_cache_pressure文件中的值**,以告诉 Linux 与pagecache 和 swap 相比更快地从dentryinode 对象中回收内存。 Inodedentry是 Linux 内核中的数据结构,分别代表文件和目录。

sysfs 选项的默认值为100。众所周知,在运行数据密集型应用程序的系统上将此设置为更大的值(如 150 或 200)会有所帮助 。我们可以使用以下命令来做到这一点:

$ echo 150 > /proc/sys/vm/vfs_cache_pressure

4.2. 在cgroups中设置绝对限制

另一种限制缓冲区缓存使用的内存量的方法是通过控制组 (也称为cgroups)。cgroups提供了一种将一个或多个进程分组以限制它们使用的资源的方法。因此,我们可以利用该功能来**设置进程可以获得多少内存的上限。**让我们看看如何创建一个新的cgroup 并设置属于该组的进程可以获得的最大内存。

首先,我们需要确定我们使用的是cgroups v1 还是 v2 ,因为选项会根据版本而变化。在这里,我们将重点关注cgroups v2,因为这是更新的。cgroups v1的说明非常相似

我们将从创建一个名为 foo 的新cgroup开始 :

$ sudo cgcreate -t $USER:$USER -a $USER:$USER -g memory:/foo

如果上述命令不可用,我们可能需要安装cgroup-toolslibcgroup,具体取决于我们的发行版。 接下来,让我们将该cgroup上限设置为 2 GB

$ sudo echo 2G > /sys/fs/cgroup/foo/memory.max

请注意,此限制应始终是内核页面大小的倍数。这就是为什么它不会恰好是 2 GB 的原因。我们可以使用以下命令验证此限制是否到位:

$ cgget -g memory:/foo/ | grep memory.max
memory.max: 2147483648

一切就绪后,我们分配给 foo 的每个进程将最多占用 2 GB 内存。