fio 测试中的 iodepth 到底是什么意思?是队列深度吗?

fio 测试中的 iodepth 到底是什么意思?是队列深度吗?

我理解队列深度是存储控制器可以处理的未完成 I/O 请求的数量(https://www.tomshardware.com/reviews/ssd-gaming-performance,2991-3.html) 即,这是处理 I/O 请求并将命令发送到磁盘 (r/w) 的存储控制器的限制,如果请求数超过其可处理的数量,它(不是严格意义上的?)就会丢弃请求(大概会由客户端重新提交)。

而出现高超出 I/O 请求的原因可能是多个客户端连接请求 I/O,或者甚至单个主机的多个进程请求 I/O(我是这样认为的,但似乎操作系统使用 I/O 调度程序合并 I/O 请求 - 这些请求来自执行定期或按需同步时的缓冲区,并且只发送固定数量的超出请求,这样就不会使存储设备过载?)

现在,来看看 fio 手册页中 iodepth 的定义:

针对文件保持飞行状态的 I/O 单元数。请注意,将 iodepth 增加到 1 以上不会影响同步 ioengines(使用 verify_async 时的小程度除外)。

这符合我对队列深度的理解。如果 IO 是同步的(阻塞 IO),我们只能有一个队列。

即使异步引擎也可能施加操作系统限制,导致无法实现所需的深度。当使用 libaio 且未设置“direct=1”时,Linux 上可能会发生这种情况,因为缓冲 I/O 在该操作系统上不是异步的。

对整个说法感到困惑。

密切关注 fio 输出中的 I/O 深度分布,以验证实现的深度是否符合预期。默认值:1。

我已经针对每个 iodepth 和设备类型运行了多个测试,其中有 22 个并行作业,因为 CPU 数量为 24,并且 rwtype:顺序读取和顺序写入。iodepth 为 1、16、256、1024、32768(我知道 32 或 64 应该是最大限制,我只是想尝试一下)。

并且对于所有深度和所有磁盘(RAID 6 SSD、NVME 和 NFS),结果几乎相同:除了在深度为 32768 的 NVME 磁盘上进行顺序读取。

IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%
submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.1%, 32=0.0%, 64=0.0%, >=64=0.0%

对于深度为 32768 的 NVME,

complete  : 0=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=100.0%

我在 fio 中使用了 libaio 引擎(因为我不确定异步 I/O 测试需要使用什么 IO 引擎,而 libaio 似乎是正确的。这完全是另一个问题)

那么,发生了什么事?为什么提交和完成显示 1-4(除了一次 NVME 运行,它 >64)

[global]
lockfile=none
kb_base=1024
fallocate=posix
blocksize=64k
openfiles=100
ioengine=libaio
buffered=1
invalidate=1
loops=5
randrepeat=1
size=512M
numjobs=22

[sr-iodepth-1]
description="Sequential Write,Parallel jobs-22,IO depth-1,libaio"
readwrite=write
size=5G
iodepth=1

[sr-iodepth-16]
description="Sequential Write,Parallel jobs-22,IO depth-16,libaio"
readwrite=write
size=5G
iodepth=16

[sr-iodepth-256]
description="Sequential Write,Parallel jobs-22,IO depth-256,libaio"
readwrite=write
size=5G
iodepth=256

[sr-iodepth-1024]
description="Sequential Write,Parallel jobs-22,IO depth-1024,libaio"
readwrite=write
size=5G
iodepth=1024

[sr-iodepth-32768]
description="Sequential Write,Parallel jobs-22,IO depth-32768,libaio"
readwrite=write
size=5G
iodepth=32768


[sw-iodepth-1]
description="Sequential Read,Parallel jobs-22,IO depth-1,libaio"
readwrite=read
size=512M
iodepth=1

[sw-iodepth-16]
description="Sequential Read,Parallel jobs-22,IO depth-16,libaio"
readwrite=read
size=512M
iodepth=16

[sw-iodepth-256]
description="Sequential Read,Parallel jobs-22,IO depth-256,libaio"
readwrite=read
size=512M
iodepth=256

[sw-iodepth-1024]
description="Sequential Read,Parallel jobs-22,IO depth-1024,libaio"
readwrite=read
size=512M
iodepth=1024

[sw-iodepth-32768]
description="Sequential Read,Parallel jobs-22,IO depth-32768,libaio"
readwrite=read
size=512M
iodepth=32768

答案1

(请不要在一个帖子中提出多个问题 - 这会使回答真的难的...)

队列深度,即未完成的 I/O 请求数 [...] 它处理 I/O 请求并将命令发送到磁盘 (r/w),并且它(不是严格意义上的?)丢弃请求

过多的请求通常不会被丢弃 - 只是设备中没有地方将它们排队,所以其他东西(例如操作系统)必须保留它们并在有可用空间时提交它们。它们并没有丢失,只是没有被接受。

导致 I/O 请求过多的原因

原因有很多 - 您列出了其中之一。例如,设备可能很慢(比如老式 SD 卡),甚至无法跟上一个“客户端”的速度。

只有固定数量的未完成请求,这样就不会使存储设备超载?)

这是目标,但没有任何迹象表明设备能够跟上(有时由于某些原因/配置导致合并不会发生)。

即使异步引擎也可能施加操作系统限制,导致无法实现所需的深度。当使用 libaio 且未设置“direct=1”时,Linux 上可能会发生这种情况,因为缓冲 I/O 在该操作系统上不是异步的。

对整个说法感到困惑。

Linux 的一个怪癖是非O_DIRECTI/O(默认)会经过缓冲区缓存(这就是所谓的缓冲 I/O)。因此,即使您认为您已经异步提交(通过使用 Linux AIO),但实际上您最终得到的只是同步行为。请参阅https://github.com/axboe/fio/issues/512#issuecomment-356604533寻求不同措辞的解释。

为什么提交并完成显示1-4

您的配置如下:

buffered=1

您没有留意之前所担心的警告!buffered=1相当于说direct=0。即使您有direct=1,默认情况fio下也会一次提交一个 I/O,因此如果您的设备速度太快,以至于在下一个 I/O 排队之前就完成了 I/O,您可能看不到高于 1 的深度。如果您希望强制/保证批量提交,请参阅iodepth_batch_*fioHOWTO/手册中提到的选项

好的,回到标题中的问题:

fio 测试中的 iodepth 到底是什么意思?

fio这是最大未完成 I/O 数量,尝试在内部排队(但请注意,fio由于上述和下述原因,可能永远无法实现该目标)。

[iodepth] 是队列深度吗?

也许,而且这还取决于你所说的“队列深度”是什么意思。如果你指的是Linuxavgqu-sz等工具所报告的iostatiodepth 可能相似或截然不同,这取决于所使用的 ioengine、该 I/O 引擎所使用的选项、提交的 I/O 的类型和样式、它必须经过的层直到到达所报告的级别等。

我认为你已经在很多不同的地方问过这些问题的变体 - 例如fio 邮件列表对上述部分问题进行了解答- 并且该邮件提到你还发布了 https://unix.stackexchange.com/questions/459045/what-exactly-is-iodepth-in-fio。您可能需要小心,因为您可能会让人们回答实际上已经在其他地方回答过的问题,而您没有将它们链接在一起,这使得发现重复的答案变得困难……

答案2

https://tobert.github.io/post/2014-04-17-fio-output-explained.html

submit 和 complete 表示 fio 一次提交的 IO 数量和一次完成的 IO 数量。在用于生成此输出的抖动测试中,iodepth 的默认值为 1,因此 100% 的 IO 都是一次提交 1 个,结果位于 1-4 个桶中。基本上,只有当 iodepth 大于 1 时,这些才重要。

这意味着第一行显示您在任何时间点拥有的未完成 IO 数量,并且这与您定义的 iodepth 一致。

提交行显示每次提交时提交了多少个 IO,这实际上表明每次提交 4 个 IO,完整的行显示每个轮询周期返回 4 个 IO,因此 fio 也提交了 4 个 IO 作为回报。

一般而言,IO 深度和队列深度相同。它们是设备/控制器一次可以处理的 IO 数量,其他 IO 将在 OS/应用程序级别的队列中等待处理。

使用低队列深度可降低延迟,使用高队列深度可提高吞吐量。设备使用队列深度实现内部并行 (SSD) 和/或重新排序和合并相关 IO(HDD 和 SSD)。

相关内容