在 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 磁盘的成像速度,因此减慢这些操作以利于系统平稳运行的解决方案对我来说很好。
写入磁盘映像时,请使用
dd
withoflag=direct
。O_DIRECT 写入将避免通过页面缓存写入数据。注意oflag=direct
将需要更大的块大小,以获得良好的性能。这是一个例子:注意:有时您可能希望通过管道传输来自另一个程序的磁盘映像,例如
gunzip
. 在这种情况下,良好的性能还取决于通过另一个命令进行iflag=fullblock
管道传输。dd
此处的答案中有一个完整的示例:为什么 gunzip 到 dd 管道最后会变慢?(另一种解决方案是使用
oflag=sync
而不是oflag=direct
. 这可以通过不构建大量未写入的缓存页面来实现)。他们是这样。但是,写入的数据首先存储在系统页面缓存中(在 RAM 中),然后再排队 IO...
编辑:
由于这个答案被接受,我假设你重新测试了
oflag=direct
,它解决了你的问题,即“系统刚刚开始爬行”。伟大的。最安全的选择也是添加
iflag=direct
。如果没有这个选项,dd
仍然是通过系统页面缓存读取数据。我假设您在没有告诉我的情况下没有添加此选项。这是对您的具体问题的一个提示。应该清楚的是,通过页面缓存读取过多的数据可能会影响系统性能。您通过页面缓存推送的数据总量是系统 RAM 的几倍 :-)。根据读取的模式,内核可以决定开始丢弃(或交换)其他缓存数据以腾出空间。
内核没有万无一失的远见。如果您需要使用从缓存中删除的数据,则必须从您的磁盘/SSD 重新加载。证据似乎告诉我们这不是你的问题。
脏页缓存限制
但是,您的问题更有可能与通过页面缓存写入数据有关。未写入的缓存,也就是“脏”页缓存,是有限的。例如,您可以想象整个脏页缓存被限制为 RAM 的 20%。(这是一个方便想象的谎言。真相在这里写得乱七八糟)。
如果您的
dd
命令设法填满最大的脏页缓存,它们将被迫“阻塞”(等待),直到一些数据被写出。但同时,任何其他想写的程序也会被阻塞(除非它使用O_DIRECT)。这可能会使您的许多桌面程序停止运行,例如当它们尝试写入日志文件时。即使他们正在写入不同的设备。
整体脏限制被命名为
dirty_ratio
ordirty_bytes
。但整个故事要复杂得多。不同设备的脏缓存之间应该存在某种程度的仲裁。有较早的阈值启动,并试图限制任何一台设备使用的最大脏缓存的比例。不过,很难理解这一切到底有多好。我认为您提到在映像“多个 USB 磁盘”时遇到问题。例如,当您尝试写入其中一个磁盘时,每个设备的阈值可能效果很好,但一旦您同时写入多个磁盘,就会崩溃。但这只是一个想法;我不知道到底发生了什么。
有关的:
一些用户在写入慢速 USB 记忆棒时观察到他们的整个系统滞后,并发现降低整体脏限制有助于避免滞后。我不知道对此有什么好的解释。
为什么在 2013 年报告了“U 盘失速”问题?为什么现有的“No-I/O 脏节流”代码没有解决这个问题?
“写回节流”是解决“USB 记忆棒失速问题”的方法吗?