sudo dd if=/dev/sda of=/dev/null bs=1M iflag=direct
atopsar -d 5 # in a second terminal
top # in a third terminal
结果来自atopsar
:
19:18:32 disk busy read/s KB/read writ/s KB/writ avque avserv _dsk_
...
19:16:50 sda 18% 156.5 1024.0 0.0 0.0 5.0 1.15 ms
19:16:55 sda 18% 156.3 1024.0 0.0 0.0 4.9 1.15 ms
...
为什么报告的磁盘利用率(“忙碌”)远低于 100%?
根据top
,该dd
进程仅使用 3% 或更少的 CPU。 还提供了系统 CPU 的硬件和软件中断 (和) 使用情况top
的总体报告,显示低于 1%。我有四个 CPU(2 个内核,每个内核有 2 个线程)。hi
si
/dev/sda
是SATA硬盘。它不是 SSD,甚至不是混合 SSHD 驱动器。它的读取速度不能超过每秒 150 兆字节 :-)。所以这部分结果是有意义的:156 read/s * 1024 KB/read = 156 MB/s
内核版本是5.0.9-200.fc29.x86_64
(Fedora Workstation 29)。IO 调度程序是mq-deadline
. 从内核版本 5.0 开始,Fedora 使用多队列块层。因为单个队列块层已被删除:-)。
我相信磁盘利用率数据是根据内核 iostat 字段之一计算得出atopsar -d
的。链接的文档提到“字段 10 - 花费在 I/O 上的毫秒数”。还有一个更详细的定义,虽然我不确定它提到的功能是否仍然存在于多队列块层中。据我所知,两者都使用通用代码来读取这个字段 10. (我相信这个字段也被//使用)atop
atopsar -d
atop
sar -d
iostat -x
mxiostat.py
附加测试
变体 2:更改为bs=512k
,但保留iflag=direct
。
dd if=/dev/sda of=/dev/null bs=512k iflag=direct
19:18:32 disk busy read/s KB/read writ/s KB/writ avque avserv _dsk_
...
19:18:00 sda 35% 314.0 512.0 0.0 0.0 2.1 1.12 ms
19:18:05 sda 35% 313.6 512.0 0.2 4.0 2.1 1.11 ms
变体 3:使用bs=1M
,但删除iflag=direct
. dd
使用大约 10% 的 CPU 和 35% 的磁盘。
dd if=/dev/sda of=/dev/null bs=1M
19:18:32 disk busy read/s KB/read writ/s KB/writ avque avserv _dsk_
...
19:21:47 sda 35% 242.3 660.2 0.0 0.0 5.4 1.44 ms
19:21:52 sda 31% 232.3 667.8 0.0 0.0 9.5 1.33 ms
如何重现这些结果 - 基本细节
当心最后的测试,即在dd
没有的情况下运行 iflag=direct
这有点像猪。我看到它冻结系统(鼠标光标)十秒钟或更长时间。即使我禁用了交换。(测试用buff/cache填充你的 RAM 。它正在填充非活动 LRU 列表。我认为周转相对较快地驱逐非活动缓存页面。同时,磁盘忙于顺序读取,因此在需要时需要更长的时间将某些内容分页。这可能会变得多么糟糕,这可能取决于内核最终是否也翻转了活动 LRU 列表,或者将其缩小太多。即当前的“多种不同算法的混搭效果如何,并进行了一些修改捕捉极端情况和各种优化”适用于您的情况)。
第一次测试的确切结果很难重现。
有时,KB/read
显示为512
而不是1024
. 在这种情况下,其他结果看起来更像bs=512k
. 包括它显示大约 35% 的磁盘利用率,而不是大约 20%。无论哪种情况,我的问题都成立。
如果您想了解这种行为,请参阅此处:为什么我的 IO 请求的大小被限制为大约 512K?
这是内核版本 5.0 更改的结果:
(
io_ticks
在part_stat_show()中使用,为“字段 10 - # of milliseconds 花在执行 I/O 上的时间”提供内核 IO 统计信息。)这很好地解释了我的结果。在 Fedora 内核配置中,“ jiffy ”是 1 毫秒。我预计提交的大型读取 IO
dd
可能会等待超过一两个 jiffies。特别是在我的系统上,它使用老式的机械硬盘。当我回到之前的内核系列 4.20.x 时,它显示了正确的磁盘利用率:
这个旧内核默认使用传统的单队列块层和
cfq
IO 调度程序。deadline
使用IO 调度器的结果也是一样的。更新:自内核 5.7 起,此近似值已调整。问题中的命令再次显示 100% 磁盘利用率。对于一些更复杂的工作负载(尽管我还没有注意到),预计新的近似值会被分解。