我了解队列深度,即存储控制器可以处理的未完成 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 请求 - 在进行定期或按需同步时源自缓冲区,并且仅发送固定数量的 outstading 请求,这样就不会使存储设备过载?)
现在,来到 fio 手册页中 iodepth 的定义:
要针对文件保持运行的 I/O 单元数。请注意,将 iodepth 增加到 1 以上不会影响同步 ioengine(使用 verify_async 时的小度数除外)。
这符合我对队列深度的理解。如果 IO 是同步的(阻塞 IO),我们可以只有一个队列。
甚至异步引擎也可能会施加操作系统限制,导致无法达到所需的深度。这可能在 Linux 上使用 libaio 而未设置 `direct=1' 时发生,因为缓冲 I/O 在该操作系统上不是异步的。
对整个声明感到困惑。
密切关注 fio 输出中的 I/O 深度分布,以验证达到的深度是否符合预期。默认值:1。
我为每种 iodepth 和设备类型运行了多个测试,有 22 个并行作业,因为 CPU 计数为 24,并且 rwtype:顺序读取和顺序写入。Iodepths 是 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
(请不要在一篇文章中提出多个问题——这会让回答变得非常困难......)
过多的请求通常不会被丢弃——设备中没有地方将它们排队,所以其他东西(例如操作系统)必须保留它们并在空间可用时提交它们。他们没有迷失,只是不被接受。
有许多不同的原因 - 您列出了其中之一。例如,设备可能很慢(想想老式的 SD 卡),即使有一个“客户端”也无法跟上。
这是目标,但没有什么可以说设备将能够跟上(有时有一些原因/配置不会发生合并)。
Linux 的一个怪癖是非
O_DIRECT
I/O(默认)通过缓冲区高速缓存(这就是所谓的缓冲 I/O)。正因为如此,即使您认为您已经异步提交(通过使用 Linux AIO),您实际上最终只是以同步行为结束。有关不同措辞的解释,请参阅https://github.com/axboe/fio/issues/512#issuecomment-356604533。你的配置有这个:
你没有注意到你之前想知道的警告!
buffered=1
是一样的说法direct=0
。即使您确实有direct=1
,默认情况下fio
一次提交一个 I/O,因此如果您的设备速度如此之快以至于它在下一个排队之前完成了 I/O,您可能不会看到高于 1 的深度。如果您希望强制/保证批量提交,请参阅HOWTO/manualiodepth_batch_*
中提到的选项fio
。好的,回到标题中的问题:
这是
fio
将尝试在内部排队的未完成 I/O 的最大数量(但请注意,fio
由于上面和下面给出的原因,可能永远无法达到它)。也许更进一步,它还取决于您所说的“队列深度”是什么意思。如果您的意思是
avgqu-sz
由诸如 Linux 之类的工具报告的,iostat
那么根据所使用的 ioengine、与该 I/O 引擎一起使用的选项、I/O 的类型和样式等因素,它们iodepth
可能相似或大不相同提交,它必须经过的层,直到它达到被报告的级别等。我想你已经在很多不同的地方问过这些问题的变化——例如,fio 邮件列表对上述一些问题有答案——而且邮件提到你也在 https://unix.stackexchange.com/questions /459045/what-exactly-is-iodepth-in-fio。您可能需要小心,因为您可能会让人们回答实际上已经在其他地方回答过的问题,并且您没有将它们联系在一起,这使得发现重复的答案变得困难......
来自https://tobert.github.io/post/2014-04-17-fio-output-explained.html
这意味着第一行显示了您在任何时间点拥有的未完成 IO 的数量,这与您定义的 iodepth 一致。
提交行显示每次提交时提交了多少个 IO,这基本上表明一次提交 4 个 IO,完整的行显示每个轮询周期返回 4 个 IO,因此 fio 也提交了 4 个 IO 作为回报.
一般来说,io 深度和队列深度是相同的。它们是设备/控制器一次可以处理的 IO 数量,其他 IO 将在操作系统/应用程序级别的队列中挂起。
您使用较低的队列深度来获得较低的延迟,并使用较高的队列深度来获得更好的吞吐量。该设备将队列深度用于内部并行 (SSD) 和/或相关 IO(HDD 和 SSD)的重新排序和合并。