如何更改所有设备的默认 BDI `max_ratio` 和/或 `min_ratio`?

如何更改所有设备的默认 BDI `max_ratio` 和/或 `min_ratio`?

我使用的系统具有多个具有不同写入吞吐量的存储设备。正如问题中所解释的为什么 2013 年会出现“U 盘失速”问题?为什么现有的“无 I/O 脏节流”代码没有解决这个问题?默认情况下,Linux 允许单个慢速设备使用几乎所有磁盘缓存进行写入缓冲,这会导致所有进程的性能较差,即使这些进程写入其他设备也是如此。如果任何进程使用void sync(void)停止来写入整个缓存,情况会变得更糟。例如,如果一个进程正在将 ISO 映像写入慢速 USB 记忆棒,则整个映像可能从进程开始就位于内核缓存中,因此sync()最终会等待整个 ISO 映像写入慢速记忆棒。

即使没有进程调用void sync(void),所有程序都会变慢,因为如果当前系统范围的写入缓存超过字节,所有程序都将被迫使用同步写入,而不是像往常一样使用后台写入/proc/sys/vm/dirty_background_bytes

我希望通过防止单个(或多个并行运行)慢速存储设备减慢整个系统的速度来避免这种情况。据我所知,这需要限制单个慢速设备的写入缓冲的缓存使用量。缓存应该足够大,以便慢速和快速设备成为使用这些设备的任何进程的瓶颈,但这些进程不受其他设备的限制,就像默认配置中发生的那样。

我发现,如果我限制/proc/sys/vm/dirty_background_bytes为 50 MB 和/proc/sys/vm/dirty_bytes200 MB,那么系统的延迟永远不会变得真正糟糕,但当我写入慢速设备时,速度仍然会变慢。我认为发生这种情况是因为当使用超过 50 MB 脏缓存时,所有写入都被强制同步。如果我们假设写入慢速内存的进程在缓存中有 52 MB,而另一个进程想要将 4 KB 文件写入另一个快速 SSD 设备,则该 4 KB 写入也必须同步,这会导致 SSD 设备速度变慢速度而不是以 RAM 速度运行。另一方面,当写入真正快速的 SSD 设备时,最大 200 MB 写入缓存可能太小,因为生成数据的进程可能不够快,无法填充缓存。因此,严格限制这两个内核设置是避免最坏情况延迟但获得非最佳平均性能的权衡。

我知道,如果我将设备 BDI 设置max_ratio为小于 的值100,那么该值将用作可用于该设备的整个写入缓存的百分比。

然而,任何设备的默认设置都是100允许任何慢速设备强制整个系统慢下来。我已经测试过,将max_ratio值设置为下面的方式100效果很好,并且可以防止慢速设备造成任何减速,因为该设备不能浪费所有缓存。

如何为所有设备(包括将来连接的设备)设置max_ratio小于的值?100我可以编写一个在系统启动期间运行的脚本并配置所有连接的设备,但随后新连接的存储(无论是 USB、eSATA 或任何其他连接方法)被允许获取所有写入缓存。

答案1

您可以使用规则为所有设备进行配置max_ratio(和) 。例如,您可以简单地创建名为as 的新文件,其中包含内容min_ratioudev/etc/udev/rules.d/90-bdi-set-min_ratio-and-max_ratio.rulesroot

# For every BDI device, set max cache usage to 30% and min reserved cache to 2% of the whole cache
ACTION=="add|change", SUBSYSTEM=="bdi", ATTR{min_ratio}="2", ATTR{max_ratio}="30"

(文件的语法*.rules是用于==检查当前状态并=应用任何操作。在这种情况下,我们告诉udev监视子系统bdi,并且每当添加或更改设备时,应用规则ATTR{min_ratio}="2"ATTR{max_ratio}="30".

创建该文件后,您可以重新启动系统或仅运行sudo udevadm trigger以应用新规则。 (这适用于 Ubuntu 18.04 或更高版本,一些旧版本可能还需要sudo udevadm control --reload-rules在运行trigger命令之前运行。)

您可以使用以下命令检查所有设备的当前状态

$ grep . /sys/devices/virtual/bdi/*/{min,max}_ratio

使用上例中的值(2 和 30)告诉系统为任何给定设备保留至少 2% 的缓存,并允许单个设备使用最多允许的最大缓存的 30%。我不知道如果您有 3 个存储设备并设置min_ratio为 50 会发生什么,因为从逻辑上讲您需要为这些设备保留总缓存空间的 150%。如果您对此进行测试,请在下面添加评论。

我还没有测试它如何与设置巨大dirty_bytes和值交互,但如果我正确理解了内核行为,则在写入缓存至少包含 ( + ) /字节或这些值总和的 50%dirty_background_bytes之前,不会强制执行这些限制。因此,如果允许巨大的缓存,则为 和 设置非常低的百分比实际上并不能阻止系统使用大量 RAM 进行缓存。假设内核总是使用+总和的一半用于写入缓存,您可以平衡另一半。未来的内核可能会改进这一点,但如果我理解正确的话,内核开发人员使用当前的实现来减少在一切顺利运行时跟踪写入缓存的哪一部分用于哪个设备的开销。dirty_bytesdirty_background_bytes2min_ratiomax_ratiodirty_bytesdirty_background_bytes

最好只提高min_ratio所有性能实际上很重要的设备,以防止慢速设备使用缓存而不是那些设备,但这需要进行更多基准测试才能更好地了解内核行为。我选择max_ratio的值30允许最多 3 个慢速设备并行工作,并且仍然有 10% 的缓存可用于快速设备(尚未受到带宽限制)。由于内核默认使用一半的缓存并max_ratio平衡另一半,这实际上将限制设置为 0.5 + 0.5 * 0.3 或大约允许用于单个慢速设备的最大磁盘缓存的 65%。

请注意,您可以对分区或完整设备应用 BDI 限制。我假设在 RAID 的情况下,您可以对该 RAID 中的单个分区、整个 RAID 设备或 RAID 中的单个设备应用 BDI 限制。上面的udev脚本将限制应用于所有级别,我不确定这是否是最佳的。最好仅将限制应用于底层设备。

相关内容