一个 16K 随机读取 I/O 在 Linux 中发出 2 个 scsi I/O(16K 和 4K)请求

一个 16K 随机读取 I/O 在 Linux 中发出 2 个 scsi I/O(16K 和 4K)请求

在对 Linux (2.6.18) 中的文件随机读取 I/O 进行基准测试时,我注意到了一个奇怪的问题。基准测试程序是我自己编写的程序,它只是不断地从随机偏移量读取 16KB 的文件。

我通过 systemtap 跟踪了系统调用级别和 scsi 级别的 I/O 行为,并注意到一个 16KB sysread 发出了 2 个 scsi I/O,如下所示。

SYSPREAD random(8472) 3, 0x16fc5200, 16384, 128137183232 
SCSI random(8472) 0 1 0 0 start-sector: 226321183 size: 4096 bufflen 4096 FROM_DEVICE 1354354008068009
SCSI random(8472) 0 1 0 0 start-sector: 226323431 size: 16384 bufflen 16384 FROM_DEVICE 1354354008075927
SYSPREAD random(8472) 3, 0x16fc5200, 16384, 21807710208 
SCSI random(8472) 0 1 0 0 start-sector: 1889888935 size: 4096 bufflen 4096 FROM_DEVICE 1354354008085128
SCSI random(8472) 0 1 0 0 start-sector: 1889891823 size: 16384 bufflen 16384 FROM_DEVICE 1354354008097161
SYSPREAD random(8472) 3, 0x16fc5200, 16384, 139365318656 
SCSI random(8472) 0 1 0 0 start-sector: 254092663 size: 4096 bufflen 4096 FROM_DEVICE 1354354008100633
SCSI random(8472) 0 1 0 0 start-sector: 254094879 size: 16384 bufflen 16384 FROM_DEVICE 1354354008111723
SYSPREAD random(8472) 3, 0x16fc5200, 16384, 60304424960 
SCSI random(8472) 0 1 0 0 start-sector: 58119807 size: 4096 bufflen 4096 FROM_DEVICE 1354354008120469
SCSI random(8472) 0 1 0 0 start-sector: 58125415 size: 16384 bufflen 16384 FROM_DEVICE 1354354008126343

如上所示,一个 16KB 预读发出 2 个 scsi I/O。(我使用探针 scsi.iodispatching 跟踪了 scsi io 调度。请忽略除起始扇区和大小之外的值。)

一个 scsi I/O 是应用程序请求的 16KB I/O,没问题。问题是另一个 4KB I/O,我不知道为什么 Linux 会发出该 I/O。

当然,奇怪的 4KB I/O 会降低 I/O 性能,我遇到了麻烦。我也使用 fio(著名的 I/O 基准测试工具)并注意到了同样的问题,所以这不是应用程序的问题。

有人能向我解释一下吗?

答案1

这可能是一个您已经检查过的愚蠢/显而易见的事情,但是您的文件系统是否已使用该noatime标志安装?

如果你没有指定,noatime那么 Linux 需要在每次访问文件时更新 inode(以设置A访问时间),这意味着它必须读取包含 inode 的磁盘区域,然后将其写回。(顺便说一句,这就是为什么性能至关重要的读取密集型文件系统应该使用noatime- 不断更新 inode 的 I/O 是巨大的,并且可能会对性能造成明显的影响)。

答案2

我知道发生了什么事,但我不知道它是做什么用的。

Ext3 文件系统每 4096KB(8192 个扇区)数据中都有一些 4KB 数据。从视觉上看,数据排列如下。

|4KB|4096KB|4KB|4096KB|4KB|4096KB| ...

而4096KB区域是只供应用程序访问的,当第一次访问第一个4096KB区域时,OS会先读取4096KB区域之前的4KB,然后再读取4096KB区域中需要的数据。

当随机访问大型文件(与 DRAM 大小相比)时,每个 I/O 都很少有机会击中页面缓存,因此每个 I/O 请求都伴随着 4KB I/O。

问题是 4KB 数据是做什么用的?这个位置是文件系统的元数据吗?有什么办法可以删除它吗?或者有什么办法可以只清除 4096KB 区域?

欢迎提出任何意见和建议。

(我在许多具有多个内核版本的机器上进行了测试。所有机器都会发生这种情况。)

谢谢。

答案3

我搞明白了。它来自 ext3 间接块映射。(Ext3 有一个块,其中每 1024 个块都有一个块指针。)

我将文件系统更改为 ext4 后问题就消失了。(Ext4 具有更高效的块寻址方案。)

谢谢你们。

相关内容