每个设备的dirty_ratio

kub*_*zyk 4 rhel cache nfs linux-kernel cifs

我最近检查了一个几乎完全挂起的 RHEL7.2,因为它写入了 CIFS 文件系统。dirty_ratio = 30和 cifs的默认设置被缓存(用于读取和写入),这些脏页大多是 cifs 的。

在内存压力下,当系统回收大部分读缓存时,系统顽固地尝试刷新和回收脏(写)缓存。所以情况是一个巨大的 CPU iowait 伴随着极好的本地磁盘 I/O 完成时间,D 中的许多进程不间断等待和一个完全无响应的系统。OOM杀手从来没有从事过,因为免费的内存系统没有给出来。(我认为 CIFS 也有一个错误,它使刷新速度慢得令人难以置信。但别介意这里。)

我惊讶地发现内核处理刷新页面到一些慢速远程 CIFS 盒的方式与处理超快速本地 SSD 驱动器完全相同。拥有一个dirty_ratio包是不明智的,它很快就会导致 30% 的 RAM 包含来自最慢设备的脏数据的情况。真是浪费钱。

这种情况是可重现的;设置dirty_ratio = 1彻底解决问题。但是为什么我需要因为使用cifs挂载而牺牲本地磁盘的缓存?

除了完全禁用某些设备的缓存或设置vm.dirty_ratio为非常低的值之外,还有什么方法可以将快速设备“列入白名单”以获得更多写入缓存?或者让慢速设备(或像 //cifs/paths 这样的远程“设备”)使用更少的写缓存?

RHEL 7.2 的内核版本称为 3.10.0-327。(它基于 3.10.0,但包括数年的向后移植)。

sou*_*edi 7

每个设备的dirty_ratio

问:有什么方法可以将快速设备“列入白名单”以获得更多写入缓存?或者让慢速设备(或像 //cifs/paths 这样的远程“设备”)使用更少的写缓存?

有一些设置,但它们并不像您希望的那样有效。请参阅bdi(“后备设备”)对象sysfs

linux-4.18/Documentation/ABI/testing/sysfs-class-bdi

min_ratio(读写)

在正常情况下,每个设备都会获得总回写缓存的一部分,该缓存与其当前相对于其他设备的平均写出速度有关。

'min_ratio' 参数允许将回写缓存的最小百分比分配给特定设备。例如,这对于提供最低 QoS 很有用。

max_ratio(读写)

允许限制特定设备使用不超过给定百分比的回写缓存。这在我们希望避免一个设备占用全部或大部分回写缓存的情况下很有用。例如,在 NFS 挂载容易卡住的情况下。

问题是“此设置仅在我们总共有超过 (dirty_background_ratio+dirty_ratio)/2 个脏数据后才生效。因为这是我们开始限制进程时的脏数据量。所以如果你想要的设备limit 是当前写入的唯一一个,限制没有太大影响。” 进一步阅读:

  • Jan Kara 的 LKML 帖子(2013 年)。
  • 本答案末尾的“测试用例”。
  • 在 v2.6.24 中提交5fce25a9df48。“如果系统上有很多空间,我们允许违反 bdi 限制。一旦我们达到总限制的一半,我们就会开始强制执行 bdi 限制......”这是添加内部每个设备的同一内核版本的一部分“限制”。所以“限制”一直是这样工作的,除了预发布版 v2.6.24-rc1 和 -rc2。

为简单起见,让我们忽略您的 30% 设置并假设默认值:dirty_background_ratio=10 和dirty_ratio=20。在这种情况下,允许进程在没有任何延迟的情况下脏页,直到整个系统达到 15% 点。

问:这种情况是可以重现的;设置dirty_ratio = 1彻底解决问题。

:-/

这听起来类似于 LWN.net 写的一篇文章关于“有害的 U 盘停顿问题”。不幸的是,这篇特别的文章具有误导性。它是如此困惑,以至于它编造了一个与报告的问题不同的问题。

一种可能性是您正在重现更具体的缺陷。如果您可以将其报告给内核开发人员,他们或许能够对其进行分析并找到解决方案。像与交互透明大页面解决。您应该使用上游内核重现该问题。或与您的付费支持联系人联系 :)。

否则,可以应用一个补丁来公开内部strictlimit设置。这使您可以更改max_ratio为严格限制。该补丁尚未应用于主线。如果有足够多的人表示对此有需求,补丁可能会被应用,或者它可能会鼓励一些工作来消除对它的需求。

我担心的是,虽然可能有用,但该功能可能不足以证明其包含的合理性。因此,我们最终将通过其他方式解决这些问题,然后我们将保留这个过时的遗留功能。

我在想,除非有人能证明这对于“足够大”的问题集来说是好的、完整的和足够的,否则我会通过补丁[1]。人们怎么看?

[1] 实际上,我会把它贴在 -mm 并维护它,所以下次有人报告问题时,我可以说“嘿,试试这个”。

——安德鲁·莫顿,2013

mm-add-strictlimit-knob-v2.patch仍然坐在-mm。有几次,人们提到了更好地自动调整脏缓存的想法。不过我还没有找到很多工作。一个吸引人的建议是为每个设备保留 5 秒的回写缓存。然而,设备的速度可能会突然改变,例如取决于 IO 模式是随机的还是顺序的。

分析(但没有结论)

问:我惊讶地发现内核处理刷新页面到一些慢速远程 CIFS 盒的方式与处理超快速本地 SSD 驱动器完全相同。

这些并不完全相同。请参阅上面 BDI 文档中的引用。“每个设备都获得了与其当前平均写出速度相关的总回写缓存的一部分。”

然而,如果慢速设备是唯一被写入的设备,这仍然使慢速设备有可能填满整个回写缓存,达到 15-20% 标记之间的某个位置。

如果您开始写入一个设备,该设备的最大回写缓存少于其允许的份额,则“脏节流”代码应该允许一些。这将使您可以使用一些剩余的余量,并避免不得不等待慢速设备为您腾出空间。

该文档建议添加 min_ratio 和 max_ratio 设置,以防您的设备速度发生不可预测的变化,包括在 NFS 服务器不可用时停顿。

问题是如果脏节流无法控制慢速设备,并且它设法填充到(或接近)20% 的硬限制。

我们感兴趣的脏节流代码在 v3.2 中被重新设计。有关介绍,请参阅 LWN.net 文章“无IO 脏节流”。此外,发布后,Fengguang Wu 在 LinuxCon Japan 上发表了演讲。他的演示幻灯片非常详细且内容丰富。

目标是将 BDI 的所有写回委托给专用线程,以实现更好的 IO 模式。但他们也不得不改用不那么直接的节流系统。充其量,这会使代码更难推理。它已经过充分测试,但我不确定它是否涵盖了所有可能的操作机制。

事实上,在 v4.18 中,您的问题的更极端版本有明确的回退代码:当一个 BDI完全没有响应时。它试图确保其他 BDI 仍然可以取得进展,但是......他们可以使用多少回写缓存将受到更多限制。即使只有一个编写器,性能也可能会下降。

Q:在内存压力下,当系统回收大部分读缓存时,系统顽固地尝试刷新和回收脏(写)缓存。因此,情况是巨大的 CPU iowait 伴随着出色的本地磁盘 I/O 完成时间,D 中的大量进程不间断等待和完全无响应的系统。OOM 杀手从未参与,因为系统没有分配可用内存。(我认为 CIFS 也有一个错误,它使刷新速度慢得令人难以置信。但在这里不要介意。)

您提到您的系统处于内存压力之下。这是一个可能非常具有挑战性的案例。当“可用”内存下降时,它会对回写缓存的大小造成压力。“dirty_ratio”实际上是“可用”内存的百分比,即空闲内存+页面缓存

这个案例是在原作中注意到的。有一种尝试来减轻它。它说“新的脏限制不会避免限制轻脏器,但可以将它们的睡眠时间限制在 200 毫秒。”

“max_ratio”的测试用例

设置一个虚拟机/笔记本电脑/不管,这并不会有昂贵的大量的内存。运行dd if=/dev/zero bs=1M of=~/test,并使用 观察写入缓存grep -E '^(Dirty:|Writeback:)' /proc/meminfo。您应该看到dirty+writeback 在“设定点”附近稳定下来。

设定点为 17.5%,介于 15% 和 20% 之间。我在 Linux v4.18 上的结果在这里。如果您想查看确切的百分比,请注意该比率不是总 RAM 的百分比;我建议你在dirty_balance_pages() 中使用tracepoint。

max_ratio在文件系统的 BDI 中使用不同的值运行了这个测试。正如预期的那样,不可能将回写缓存限制在 15% 以下。


归档时间:

查看次数:

1930 次

最近记录:

6 年,8 月 前