在 Ubuntu 18.04 系统上执行大型磁盘映像操作时,我遇到了一些系统范围的延迟/滞后问题。这是系统规格:
处理器:Intel Core i7(任何核心都不会接近容量)
内存:12GB(切勿接近容量)
系统盘:SSD(切勿接近容量)
外部磁盘:USB 3.0 5400 和 7200RPM 旋转磁盘
这些大型磁盘映像操作基本上是:
nice ionice dd if=/dev/usbdisk1 of=/dev/usbdisk2
由于我的系统文件都不位于任何 USB 磁盘上,因此从理论上讲,这不会带来太多延迟。但我发现当我对多个 USB 磁盘进行映像时,系统就会变得缓慢。为什么?我的理解是每个磁盘都有自己的IO队列,那么这里是怎么回事呢?我该如何补救?
另外,FWIW,我根本不关心 USB 磁盘的成像速度,因此减慢这些操作以有利于系统平稳运行的解决方案对我来说很好。
答案1
我该如何补救?
当您写入磁盘映像时,请使用dd
with oflag=direct
。 O_DIRECT 写入将避免通过页缓存写入数据。注意oflag=direct
需要更大的块大小,才能获得良好的性能。这是一个例子:
dd if=/dev/usbdisk1 of=/dev/usbdisk2 oflag=direct bs=32M status=progress
注意:有时您可能希望从另一个程序(例如gunzip
.在这种情况下,良好的性能还取决于iflag=fullblock
并通过另一个dd
命令进行管道传输。这里的答案中有一个完整的例子:为什么从gunzip到dd管道最后会变慢?
(另一种解决方案是使用oflag=sync
代替oflag=direct
。这可以通过不构建大量不成文缓存页面)。
我的理解是每个磁盘都有自己的IO队列,那么这里是怎么回事呢?
他们是这样。但是,写入的数据首先存储在系统页缓存(RAM 中)中,然后再对 IO 进行排队...
编辑:
由于这个答案被接受,我假设您重新测试了oflag=direct
,它解决了您的问题“系统刚刚爬行”。伟大的。
iflag=direct
最安全的选择是也添加。没有这个选项, dd
仍然是阅读数据通过系统页面缓存。我假设您没有在没有告诉我的情况下添加此选项。这是对您的具体问题的一种暗示。
应该清楚的是通过页缓存读取了过多的数据可以影响系统性能。您通过页面缓存推送的数据总量比系统 RAM 大几倍:-)。根据读取模式,内核可能决定开始删除(或交换)其他缓存数据以腾出空间。
内核没有绝对正确的远见。如果您需要使用从缓存中删除的数据,则必须从磁盘/SSD 重新加载它。证据似乎告诉我们这不是你的问题。
脏页缓存限制
但是,您的问题更有可能与写作数据通过页面缓存。未写缓存,又名“脏”页缓存,是有限的。例如,您可以想象整个脏页缓存限制为 RAM 的 20%。 (这是方便想象的谎言,真相写得乱七八糟这里)。
如果您的dd
命令设法填充最大脏页缓存,它们将被迫“阻塞”(等待),直到某些数据被写出。
但同时,任何其他想要写入的程序也会被阻止(除非它使用 O_DIRECT)。这可能会导致许多桌面程序停止运行,例如当它们尝试写入日志文件时。即使他们正在写入不同的设备。
总体脏限制被命名为dirty_ratio
or dirty_bytes
。但整个故事要复杂得多。不同设备的脏缓存之间应该存在某种程度的仲裁。有较早的阈值启动,并尝试限制任何一台设备使用的最大脏缓存的比例。但很难确切地理解这一切的运作效果如何。
我认为您提到在对“多个 USB 磁盘”进行映像时遇到问题。例如,当您尝试写入其中一个磁盘时,每设备阈值可能运行良好,但一旦同时写入多个磁盘,就会崩溃。但这只是一个想法;我不知道到底发生了什么。
有关的:
一些用户观察到,当写入速度较慢的 USB 盘时,整个系统会出现延迟,并发现降低总体脏限制有助于避免延迟。我不知道对此有什么好的解释。