迭代文件系统的最快方法

Posted

技术标签:

【中文标题】迭代文件系统的最快方法【英文标题】:The fastest way to iterate through file system 【发布时间】:2020-07-18 12:35:58 【问题描述】:

有时我需要递归遍历一个文件夹,读取其中所有文件的内容。

我使用 C++ 和 Linux。

文件夹内容是任意的,从十亿个小文件到十几个庞大的文件。

试图达到最高的阅读速度,我陷入了两难境地。 一方面,从一个线程执行所有读取几乎总是更快,因为对文件系统的并行访问会导致并发读取文件之间的头部抖动:

另一方面,从一个线程对文件系统的顺序访问并没有尽可能快,原因有两个。

首先,从完成前一个读取请求到启动下一个读取请求之间所花费的时间会丢失。我试图通过在读取线程中除了读取自身之外什么都不做来尽可能地最小化它,但是在用户和内核空间之间不断切换它仍然一些时间丢失,尤其是在上述情况下数十亿个小文件。

其次,单线程读取不允许内核和/或 HDD 控制器对请求的扇区执行某些重新排序,这可能会提高性能。

所以,我想实现两件事:

1) 在例如LibUsb,我可以有几个待处理的读取请求,它们按顺序处理,在前一个请求的完成和下一个请求的启动之间没有暂停。 FS访问是否有可能获得类似的东西?

2)是否可以同时向内核提交多个读请求,但是以某种方式标记它们,以便内核知道这些请求没有个别 截止日期,并且应该尽量减少累积执行的总结时间

【问题讨论】:

现代驱动器具有已经做到这一点的 NCQ。你也试过用noatime挂载吗? @rustyx 感谢您的评论。如果没有内核的合作,从定义上讲,这个问题无法解决,因为没有它,I/O 调度程序会在一段时间后确定线程#2 等待其部分数据的时间过长,并将切换到另一个文件。单靠硬盘大脑,再先进也不够。至于noatime,只是缓解了更新元数据的痛苦,不在本题讨论范围内。 @itisravi 这正是我要找的!请将您的评论转换为答案。 @ScumCoder 将我的评论移至答案。 (PS:据称,在某些情况下,按 inode 顺序遍历事物会导致加速(我想硬盘会带来最大的好处)-github.com/borgbackup/borg/pull/932#issuecomment-211120899) 【参考方案1】:

既然您使用的是 Linux,也许您应该尝试一下新的io_uring 接口。它声称比传统的同步(线程池+阻塞 sycalls)或异步libaio 方法更高效和高性能。

对于 1,io_uringIORING_SETUP_SQPOLL 标志似乎可以满足您的需求,只要您不断提出请求。

【讨论】:

以上是关于迭代文件系统的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

重定向丢失图像文件的最快方法

获取媒体文件持续时间的最快方法是啥?

如何用最快的速度读出大小为10G的文件的行数?弄懂 python 的迭代器

获取递归包含在目录中的文件列表的最快方法是啥?

在 Node.js 中复制文件的最快方法

通过网络传输文件的最快方法是啥(FTP、HTTP、RSync 等)[关闭]