在外部磁盘上执行大型 R/W 操作时系统滞后

Mr.*_*. T 6 performance io dd usb-drive

在 Ubuntu 18.04 系统上执行大型磁盘映像操作时,我遇到了系统范围的延迟/滞后问题。这是系统规格:

处理器:英特尔酷睿 i7(任何内核都不会接近容量)

内存:12GB(永不接近容量)

系统盘:SSD(永不接近容量)

外部磁盘:USB 3.0 5400 和 7200RPM 旋转磁盘

这些大型磁盘映像操作基本上是:

nice ionice dd if=/dev/usbdisk1 of=/dev/usbdisk2

由于我的系统文件都不在任何 USB 磁盘上,理论上,这不应该引入太多延迟。但是我发现当我对多个 USB 磁盘进行映像时,系统就会开始爬行。为什么?我的理解是每个磁盘都有自己的IO队列,那这是怎么回事呢?我该如何补救?

另外,FWIW,我根本不在乎 USB 磁盘的成像速度,因此我认为可以减慢这些操作以促进系统平稳运行的解决方案。

sou*_*edi 6

我该如何补救?

写入磁盘映像时,请ddoflag=direct. O_DIRECT 写入将避免通过页面缓存写入数据。注意oflag=direct将需要更大的块大小,以获得良好的性能。下面是一个例子:

dd if=/dev/usbdisk1 of=/dev/usbdisk2 oflag=direct bs=32M status=progress
Run Code Online (Sandbox Code Playgroud)

注意:有时您可能希望从另一个程序(例如gunzip. 在这种情况下,良好的性能还取决于iflag=fullblock并通过另一个dd命令进行管道传输。这里的答案中有一个完整的例子:为什么到 dd 管道的 gunzip 最终会变慢?

(另一种解决方案是使用oflag=sync而不是oflag=direct。这是通过不建立大量写入的缓存页面来工作的)。

我的理解是每个磁盘都有自己的IO队列,那这是怎么回事呢?

他们是这样。但是,写入的数据首先存储在系统页面缓存中(在RAM中),然后再排队IO...


编辑:

既然这个答案被接受了,我假设你重新测试了oflag=direct,它解决了你的问题,即“系统刚刚开始爬行”。伟大的。

最安全的选择是添加iflag=direct。如果没有这个选项, dd仍然是通过系统页面缓存读取数据。我假设您没有告诉我就没有添加此选项。这是对您的具体问题的一个提示。

应该清楚的是,通过页面缓存读取过多数据影响系统性能。您通过页面缓存推送的数据总量比您的系统 RAM 大几倍:-)。根据读取模式,内核可以决定开始丢弃(或交换)其他缓存数据以腾出空间。

内核没有绝对可靠的远见。如果您需要使用从缓存中删除的数据,则必须从您的磁盘/SSD 重新加载。证据似乎告诉我们这不是你的问题。

脏页缓存限制

但是,您的问题更有可能与通过页面缓存写入数据有关。未写入的缓存,又名“脏”页面缓存,是有限的。例如,您可以想象整个脏页缓存限制为 RAM 的 20%。(这是一个方便想象的谎言。真相在这里写得乱七八糟)。

如果您的dd命令设法填充最大脏页缓存,它们将被迫“阻塞”(等待),直到一些数据被写出。

但同时,任何其他想要写入的程序也会被阻塞(除非它使用 O_DIRECT)。这可能会使您的许多桌面程序停止运行,例如,当它们尝试写入日志文件时。即使他们正在写入不同的设备。

整体脏限制被命名为dirty_ratioor dirty_bytes。但整个故事要复杂得多。不同设备的脏缓存之间应该存在某种程度的仲裁。有较早的阈值会启动,并试图限制任何一台设备使用的最大脏缓存的比例。不过,很难确切地了解这一切的运作情况。

我认为您提到在对“多个 USB 磁盘”进行映像时遇到问题。例如,当您尝试写入其中一个磁盘时,每个设备的阈值可能工作得很好,但一旦您同时写入多个磁盘,就会崩溃。但这只是一个想法;我不知道到底发生了什么。

有关的:

一些用户在向慢速 USB 记忆棒写入时观察到整个系统滞后,并发现降低整体脏限制有助于避免滞后。我不知道对此有什么好的解释。

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

“回写限制”是“USB 记忆棒停顿问题”的解决方案吗?