LWN:关于readahead的讨论!
关注了就能看到更多这么棒的文章哦~
A discussion on readahead
By Jake Edge
June 15, 2022
LSFMM
DeepL assisted translation
https://lwn.net/Articles/897786/
Readahead 是一种 I/O 优化,让系统读取的数据要比应用程序所要求的更多,因为相信这些额外的数据很快会被用上。在 2022 年 Linux 存储、文件系统、内存管理和 BPF 峰会(LSFMM)上,Matthew Wilcox 在 Steve French 和 David Howells 的协助下,主持了一次讨论 Readahead 的会议,特别是与网络文件系统有关的内容。底层存储设备的 latency 需要被考虑到预先多读取多少数据的计算过程中,但如何做到这一点,尚未完全确定。
Wilcox 首先介绍了一下 readahead。如果用户空间正在一个字节一个字节地读取一个文件,那么 Linux 实际上并不会这么做;相反,它发出更大块(bigger chunk)的读取,比如说每笔 64KB,这些数据被存储在 page cache 里。从对存储设备发起一个 page 的 read,一直到它真的出现在 page cache 中,是有一定的 latency 的;这个延迟在 Linux 支持的各种存储类型中各不相同。同样是网络存储,可以是本地存储在千兆以太网上的数据,也可以是存储在地球另一端的明显较慢的链接上的数据。同样,对于本地存储来说,既可能是每秒 5GB 的 NVMe 固态硬盘,也可能是一些 "在贸易展上从供应商处获得的蹩脚的 U 盘"。这里有 "很多不同情况需要处理"。
[Matthew Wilcox]
根据他的经验,block-layer 开发人员倾向于使用 direct I/O 来进行所有测试;他们认为 "page cache 很讨厌",所以他们在测试中避免使用它。James Bottomley 说,他们经常需要在测试中排除 page cache 的影响,以消除他们控制之外的那些变量。Wilcox 说,这其实不太好,因为用户所看到的性能表现,是包括了 page cache 在内的情况;如果能在用户之前就发现那些由于有太多的或太少的 readahead 导致性能变差的问题,那就再好不过了。
他说,他有一个 KernelNewbies 的 wiki 页面,正在收集记录他对 readahead 和 page cache 的整体的想法。page cache "在某些方面很厉害,在其他方面则很糟糕",但如果能解决它的问题就好了。安卓开发者遇到了 readahead 的问题,但 "他们以最糟糕的方式解决了这个问题"。他介绍说,他们改变了 readahead 的设置,将其从 256KB 改为了几百兆,以便能从应用程序的启动时间中减少那么 "几分之一秒"。当然,这也会有其他的影响;当他们试图向上游打 patch 时,内存管理开发者直接会拒绝。
Howells 建议,安卓开发者应该使用 fadvise()(他补充说或者是 madvise())来表示文件应该有更积极的 readahead。但 Willcox 并不同意。"我们能不能不要再假设用户空间知道自己在做什么?" Bottomley 说,安卓是一个特殊的环境;它使用了一个日志结构的文件系统,所以他们的这个方法可能真是合理的。Wilcox 对这一点表示了一些怀疑。
总的来说,有一堆 readahead 问题需要解决。"我想说 'f' 那个词了,也就是 folio,其实在其中起了一点作用。" 目前,使用较大的 folio 的场景主要是由 readahead 所引发的,readahead 数据越大,容纳它的 folio 页面就越大。这对测试是很有好处的。支持更大 folio 的文件系统,目前只有 XFS 这一个(尽管 AFS 和 v9fs 的 patch 正在排队等待合入),它会分配四个 page (所谓的 order-2)folio。
Wilcox 说,French 让他知道了 Windows 在 CIFS 上为 readahead 进行的读取是非常大的。French 同意这一点,他指出,由于预期会有网络延迟,Windows 可以将 readahead 提高到 16MB,尽管这似乎降低了性能。他用了一些各种不同大小(256KB、512KB、1MB、4MB)的场景进行了测试,发现每一种都有更好的性能,最亮眼的数据是使用 512KB 时。在 Azure 云上,该值被设置为 1MB,因为一些 workload 在 4MB 时会有性能下降。
他说,根据他的测试结果,Linux CIFS 服务器的默认值是 4MB。很明显,任何小于 1MB 的读取都会带来性能问题,除非它的网络速度非常快。他所看到的问题是如果合理地设置这个值,对它进行调小来限流,或者适当提高。有时 page cache 其实比文件系统知道的信息更加多,或者有时又更加少,并且还需要考虑 network layer 的影响。他不清楚这一切该如何解决。
Wilcox 说,有一种机制可以将这种信息从文件系统传递给虚拟文件系统(VFS)层和使用 BDI(struct backing_dev_info)的 page cache。他说这就是 VFS 利用来了解底层存储的性能特征的地方,目前它可能没有所有那些最合适的信息,但这是放置这类信息的位置。
当用户空间正在一个字节一个字节地读取文件时,就会发出 64KB 的读取;一个 "这个 readahead 是否有用 " 的标记被放置在了 buffer 中的 20KB 位置左右,当达到这个标记时,就会发出另一个 64KB 单位的读取操作。其目的是在用户空间使用完所剩下的 44KB 之前就完成第二次读取,但文件系统不知道读取的延迟是多少。他说,人们可以拍脑袋说去测量一下进行读取所需的时间,并将其与用户空间的消耗率进行比较,以更好地确定何时来安排下一次 read,但这并没有实现出来。
第二个 64KB 的读取操作,就会把 mark 标记放在 buffer 开头;当达到这个 mark 时,它决定增加 readahead buffer 并再读取 128KB。它还会再增加一次(也就是到 256KB),但不会再进一步了,尽管它可能其实应该继续增加。256KB 的限制已经存在了 20 年,"在这段时间里,I/O 几乎没有任何变化",Wilcox 讲了一句反话。目前距离当初增加这个限制的时候已经过去了很多年了。Josef Bacik 读了 Jan Kara 的聊天区评论,其中说 SUSE 多年来一直在使用 512KB 的限制。考虑到这个情况,Wilcox 认为应该立即将最大限值改为 1MB。
但是,与其直接增加读取的 size,Wilcox 更愿意发出多个 256KB 的紧挨着的 read 操作,因为这将有助于 page cache 来跟踪前面所读取的数据是否真的被使用了。French 说,这对 CIFS 来说是比较友好的,因为多个较小的 read 在性能上表现更好。Jeff Layton 通过 Zoom 插进来说,他认为单个较大的 read 对 NFS 来说更好,而听到较小的 read 在 CIFS 看来更加好,他表示很惊讶。
Howells 说,哪个选项更好,完全取决于文件系统。Ted Ts'o 说,这也将会跟底层存储设备有关;在内存受限的设备上增加 readahead 大小可能也会有问题。不会有一个 "神奇的 readahead 公式" 可以在所有情况下都适用。他建议使用 BPF 来实验不同的算法,这样的话,安排一位研究生就可以很容易地尝试各种不同的想法,看看哪种方法最有效。Wilcox 说,他本来想反驳这个想法,但后来决定他要赞同这个主意,因为这样一来就会是别人的问题了,现场哄堂大笑。
Chuck Lever 认为在讨论中,关于 readahead 的情况被大大简化了。在一个程序每次读取一个字节的原始例子中,没有理由增加到 64KB 以上,因为这就足够跟上程序运行的速度了。如果请求太多的数据,来用实际上不会被读取到的 page 填充了 page cache,这不是正确的做法。
还有一个问题,例如在网络文件系统上排队进行 1MB 的读取,在读取过程中会耽误其他较小的 request,比如 metadata 的更新。他同意需要进行实验,并认为测试应该要比立即增加内核的 readahead size 要优先完成。有必要对许多不同的 workload、文件系统所进行的测试,以确定这种改动的整体系统性影响是什么样的。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~