为什么在 2013 年会报告“U 盘停顿”问题?为什么现有的“No-I/O 脏节流”代码没有解决这个问题?

sou*_*edi 9 linux cache

有害的 USB 记忆棒停顿问题- LWN.net,2013 年 11 月。

Artem S. Tashkinov 最近遇到了一个问题,至少一些 LWN 读者会熟悉这个问题。将慢速存储设备(例如 U 盘或媒体播放器)插入 Linux 机器并向其写入大量数据。整个系统继续挂起,可能持续几分钟。

不过这一次,Artem 做了一个有趣的观察:系统在使用 64 位内核运行时会停顿,但在相同硬件上使用 32 位内核时没有遇到这样的问题。

文章解释说,对于 64 位内核,默认情况下允许脏页缓存(回写缓存)增长到内存的 20%。使用 32 位内核时,它实际上被限制在大约 180MB。

Linus 建议在 64 位上也将其限制为 ~180MB,但是当前的 Linux (v4.18) 没有这样做。将Linus 建议的补丁, 与Linux 4.18 中的当前功能进行比较。反对这种变化的最大论据来自 Dave Chinner。他指出,过多地减少缓冲会导致文件系统受到碎片化的影响。他还解释说,“对于流式 IO,我们通常需要至少 5 秒的缓存数据来平衡延迟。”

我很迷惑。优盘卡顿为什么会导致整个系统挂掉?

我很困惑,因为我读了一篇描述2011 年合并代码的早期文章(Linux 3.2)。它显示内核应该已经在每个设备的基础上控制脏页缓存:

无 I/O 脏节流- LWN.net, 2011

这就是Fengguang 的补丁集的用武之地。他试图创建一个控制循环,该循环能够确定在任何给定时间每个进程应该允许脏多少页。超出其限制的进程会被简单地休眠一段时间以允许写回系统赶上它们。

[...]

系统的目标是将脏页数保持在设定值;如果事情变得不合时宜,就会施加越来越大的力量,将事情带回应有的位置。

[...]

但是,如果不考虑支持设备 (BDI),则无法真正计算出该比率。一个进程可能正在弄脏存储在给定 BDI 上的页面,并且系统此时可能有过多的脏页面,但是限制该进程的智慧还取决于该 BDI 存在多少脏页面。[...] 具有很少脏页的 BDI 可以快速清除其积压,因此它可能负担得起更多,即使系统比人们希望的更脏。因此,补丁集使用复杂的公式调整特定 BDI 的计算 pos_ratio,该公式查看特定 BDI 与其自身设定点及其观察到的带宽之间的距离。最终结果是一个修改后的 pos_ratio,描述系统是否应该污染由给定 BDI 支持的更多或更少的页面,以及多少。

甚至在此之前添加了每设备控制:Smarter write throttling,2007 LWN.net。[PATCH 0/23] 每个设备脏节流 -v10。它已在Linux 版本 2.6.24 中合并。

sou*_*edi 9

  1. 2013年的文章有误
  2. LWN 中的错误?你确定吗?
  3. I/O 设备中的长队列,由“后台”写回创建
  4. “无 I/O 脏节流”的限制?
  5. “U盘卡顿”问题的真实报告
  6. 脏限制计算错误 [2014]
  7. 大量页面分配阻塞 IO [2011]
  8. “到达 LRU 末尾的脏页”?[2013 年之前]

1.2013年的文章有误

“U盘档”这篇文章给你的印象是非常误导的。它歪曲了原始报告和一系列回应。

当 Artem 将缓存的写入刷新到 USB 记忆棒时,它没有报告整个系统挂起。他最初的报告只是抱怨运行“同步”命令可能需要“几十分钟”。这种区别在Linus Torvalds回应中得到了明确说明:

只需使用普通的 USB 密钥并尝试对其进行写入,就可以轻松重现。我只是用一个随机的 ISO 图像来做的,这很痛苦。并不是说在后台做大多数其他事情会很痛苦,但是如果你碰巧运行了任何“同步”的东西(它发生在脚本中),事情就会戛然而止。几分钟。

2. LWN 中的错误?你确定吗?

Jon Corbet拥有 15 年的经验,每周报告 Linux 内核开发。在某种意义上,我预计这篇文章至少接近正确。所以我想处理这两个不同的记录,并找出他们同意或不同意的详细点。

我使用 lore.kernel.org 上的档案阅读了所有原始讨论。我认为这些信息非常清楚。

我 100% 肯定这篇文章曲解了讨论。在文章下方的评论中,至少有两位读者用自己的话重复了错误的说法,但没有人纠正。文章在第三段中延续了这种混淆:

所有这些数据都会阻塞 I/O 队列,可能会延迟其他操作。而且,只要有人调用sync(),事情就会停止,直到整个队列都被写入。

这可能是 Linus 所说的“事情戛然而止”的困惑。“事物”指的是“做任何事情sync”。但科贝特写的好像“这件事”意味着“整个系统”。

按照 Linus 的说法,这是一个现实世界的问题。但是绝大多数“事物”并没有调用系统范围的同步()操作。 [1]

为什么 Corbet 会将其与“整个系统”混淆?我想有很多问题,过了一段时间后,很难将它们全部分开在你的脑海中:-)。虽然 LWN 已经描述了每个设备(和每个进程)脏节流的发展,但总的来说,我认为没有太多关于此类细节的文章。很多文档只描述了全局脏限制设置。

3. I/O 设备中的长队列,由“后台”写回创建

Artem在线程中发布了第二份报告,其中“服务器几乎停止运行,其他 IO 请求需要更多时间才能完成”。

第二份报告与有关 USB 记忆棒挂起的声明不符。这是在内部磁盘上创建 10GB 文件后发生的。这是一个不同的问题。

该报告没有确认这是否可以通过更改脏限制来改善。并且最近对此类案例进行了分析。当它阻塞主磁盘的 I/O 队列时,会出现一个重大问题。您可能会在经常依赖的磁盘上遭受长时间的延迟、按需加载程序代码、使用 write() + fsync() 等保存文档和应用程序数据等。

走向不那么烦人的后台回写-- LWN.net, 2016

当内存管理代码决定写入一系列脏数据时,结果是提交给模块子系统的 I/O 请求。该请求可能会在 I/O 调度程序中花费一些时间,但它最终会被分派给目标设备的驱动程序。

问题在于,如果要写入大量脏数据,最终可能会有大量(如数千个)请求排队等待设备。即使是相当快的驱动器也需要一些时间来处理这么多请求。如果某些其他活动(例如,单击 Web 浏览器中的链接或启动应用程序)在同一个块设备上生成 I/O 请求,则这些请求将排在该长队列的后面,并且可能在一段时间内无法得到服务。如果生成了多个同步请求——例如来自新启动的应用程序的页面错误——这些请求中的每一个都可能不得不通过这个长队列。这就是事情似乎停止的地方。

[...]

大多数块驱动程序还在内部维护自己的队列。那些较低级别的队列可能特别成问题,因为当请求到达那里时,它不再受 I/O 调度程序的控制(如果有 I/O 调度程序的话)。

这些补丁在 2016 年末 (Linux 4.10)合并以改进这一点。此代码称为“回写限制”或 WBT。在网上搜索wbt_lat_usec还可以找到更多关于此的故事。(最初的文档写了关于wb_lat_usec,但已经过时了)。请注意,写回限制不适用于 CFQ 或 BFQ I/O 调度程序。CFQ 作为默认 I/O 调度程序很受欢迎,包括在 Linux v4.20 之前的默认内核构建中。 CFQ 在内核 v5.0 中被删除

SSD(看起来像 NVMe)和“普通硬盘”上都有测试来说明问题(和原型解决方案)。硬盘驱动器“不像更深的队列深度设备那么糟糕,我们有巨大的突发 IO”。

我不确定“成千上万”的排队请求,但至少有 NVMe 设备可以将数百个请求排队。大多数 SATA 硬盘允许 32 个请求排队(“NCQ”)。当然,硬盘驱动器需要更长的时间来完成每个请求。

4.“无I/O脏节流”的局限性?

“无 I/O 脏节流”是一个相当复杂的工程系统。随着时间的推移,它也得到了调整。我确信在这段代码中曾经并且仍然存在一些限制。

LWN 文章、代码/补丁注释和详细演示文稿中的幻灯片表明,已经考虑了大量场景。这包括臭名昭著的慢速 USB 记忆棒与快速主驱动器。测试用例包括短语“1000 个并发 dd”(即顺序写入器)。

到目前为止,我不知道如何演示和重现脏节流代码中的任何限制。

我已经看到了一些关于脏节流代码之外的问题修复的描述。我发现的最新修复是在 2014 年 - 请参阅后续部分。在 LWN 报道的主题中,我们了解到:

在最近的几个版本中,像这样的问题是由回收问题引起的,这些问题因看到大量脏/写回页面而受够了,最终卡在等待 IO 完成。

[...] systemtap 脚本捕获了这些类型的区域,我相信它们已修复。

梅尔·戈尔曼还表示,存在一些“悬而未决的问题”。

不过还是有问题。如果所有脏页都由慢速设备支持,那么脏限制最终仍会导致脏页平衡 [...]

这段话是我在报告的讨论线程中唯一能找到的,它几乎支持 LWN 的解释。我希望我能理解它指的是什么:-(。或者如何证明它,以及为什么它在 Artem 和 Linus 运行的测试中似乎没有成为一个重要问题。

5.“U盘卡顿”问题正版报告

尽管 Artem 和 Linux 都没有报告影响整个系统的“USB 记忆棒停顿”,但我们可以在其他地方找到一些关于此的报告。这包括最近几年的报告 - 在上次已知修复之后。

我不知道有什么区别。也许他们的测试条件在某些方面有所不同,或者自 2013 年以来内核中产生了一些新问题......

6.dirty limit计算错误[2014]

2014 年 1 月有一个有趣的修复(应用于内核 v3.14)。在问题中,我们说默认限制设置为内存的 20%。实际上,它设置为可用于脏页缓存的内存的 20%。例如,内核缓冲区为 TCP/IP 网络套接字发送数据。套接字缓冲区不能被删除并替换为脏页缓存:-)。

问题是内核正在计算可交换内存,好像它可以交换数据以支持脏页缓存。尽管这在理论上是可能的,但内核强烈倾向于避免交换,而是更喜欢丢弃页面缓存。这个问题通过 - 猜猜是什么 - 一个测试涉及写入慢速 USB 记忆棒,并注意到它导致整个系统的停顿:-)。

请参阅回复:[patch 0/2] mm:减少具有大量匿名和脏缓存的回收停顿

解决方法dirty_ratio是现在仅将其视为文件缓存的一部分。

根据遇到此问题的内核开发人员的说法,“触发条件似乎很合理 - 大量的匿名内存使用和大量缓冲 IO 和交换配置 - 并且这种情况很可能发生在野外。” 所以这可能解释了2013 年或更早的一些用户报告。

7. 巨大的页面分配阻塞 IO [2011]

这是另一个问题:巨大的页面、缓慢的驱动器和长时间的延迟(LWN.net,2011 年 11 月)。现在应该修复这个大页面问题。

此外,尽管文章说了些什么,但我认为大多数当前的 Linux PC 并没有真正使用大页面。这可能会从 Debian 10 开始改变。然而,即使 Debian 10 开始在可能的情况下分配大页面,我似乎很清楚它不会强加任何延迟,除非您将另一个设置更改defrag为“始终”。

8. “到达 LRU 末尾的脏页” [2013 年之前]

我没有研究过这个,但我发现它很有趣:

mgorman 2011:这是一种新型的与 USB 相关的停顿,因为它是由于同步压缩写入造成的,过去的大问题是脏页到达 LRU 的末尾并被 reclaim 写入

mgorman 2013:该领域的工作处理了脏页到达 LRU 末尾(CPU 使用率过高)等问题

如果这是两个不同的“到达 LRU 的尽头”问题,那么第一个听起来可能非常糟糕。听起来好像当一个脏页成为最近最少使用的页时,任何分配内存的尝试都会被延迟,直到该脏页完成写入。

不管这意味着什么,他说问题现在已经解决了。


[1] 一个例外:有一段时间,Debian 软件包管理器dpkg使用 sync() 来提高性能。这被删除了,因为 sync() 可能需要很长时间的确切问题。他们转而使用sync_file_range()在 Linux 上使用的方法。参见Ubuntu 错误 #624877,评论 62


之前尝试回答这个问题的一部分 - 这应该是多余的:

我认为我们可以将 Artem 的两份报告解释为与“No-I/O 脏节流”代码一致。

脏节流代码旨在允许每个后备设备公平分享“总回写缓存”,“这与其当前相对于其他设备的平均写出速度有关”。这句话来自/sys/class/bdi/的文档。[2]

在最简单的情况下,只写入一个后备设备。在这种情况下,设备的公平份额为 100%。write() 调用受到限制以控制整个写回缓存,并将其保持在“设定点”。

写入开始在dirty_background_ratio- 启动后台写出的点 - 和dirty_ratio- 写回缓存的硬限制之间的中途受到限制。默认情况下,这些是可用内存的 10% 和 20%。

例如,您仍然可以仅将 15% 的空间写入主磁盘。根据您拥有的 RAM 大小,您可以拥有数 GB 的缓存写入。那时, write() 调用将开始受到限制以匹配写回速度 - 但这不是问题。我预计挂起问题是 read() 和 fsync() 调用,它们会卡在大量不相关的 IO 后面。这是“回写限制”代码解决的具体问题。一些 WBT 补丁提交包括问题描述,显示了这导致的可怕延迟。

同样,您可以通过写入 USB 记忆棒来完全填满 15%。对 USB 的进一步 write() 将受到限制。但是主磁盘不会使用它的任何公平份额。如果您开始在主文件系统上调用 write() ,那么它不会受到限制,或者至少会延迟更少。而且我认为 USB write()s 会受到更多限制,以使两个编写器达到平衡。

我预计整体写回缓存可能会暂时高于设定值。在一些要求更高的情况下,您可以达到整个写回缓存的硬限制。硬限制默认为可用内存的 20%;配置选项是dirty_ratio/ dirty_bytes。也许你可以点击这个是因为设备可能会变慢(可能是因为更随机的 I/O 模式),并且脏节流不会立即识别速度的变化。


[2] 您可能会注意到该文档建议您可以手动限制可用于特定分区/文件系统的回写缓存的比例。该设置称为/sys/class/bdi/*/max_ratio。请注意,“如果您要限制的设备是当前唯一写入的设备,则限制不会产生太大影响。”


归档时间:

查看次数:

1164 次

最近记录:

4 年,8 月 前