使用C++读取文件的最快方法是什么?

3

读取文件意味着我将读取硬盘上的每个文档(doc,docx,xls,xml,txt等)。

我的大多数文件应该会在10KB〜1MB左右。

我会阅读文件并过滤文本,以查找特定单词。

因此,我猜想我应该有一个线程池和一个线程用于读取文件,其他线程用于过滤。

我听说有MMFCreateFile/ReadFile或I/O完成端口来读取每个文件。

我应该使用哪个函数?


1
顺便说一下,.docx是一个ZIP文件。 - user541686
1
一些关于为什么内存映射快速的信息,请访问https://dev59.com/aGkw5IYBdhLWcg3wi7Jz#9818473。 - Tony Delroy
3个回答

4
在我的测试中,将文件映射到内存是将内容加载到内存中的最快方式,但只比其他方式略快一些。 我的测试是在Linux上进行的,但是由于将文件加载到内存映射区域的方法是以页为单位将数据复制到由操作系统拥有的内存中(内存映射文件的后备内存完全由操作系统拥有和处理,因此操作系统有能力将该内存固定在原地等等),因此这比将文件的一部分读入内核缓冲区然后将该内容复制到应用程序提供的缓冲区要快,因为它避免了一个复制步骤。 然而,对于大型文件(或许多小文件),主要限制因素仍然是“硬盘可以传递数据的速度”,对于我的系统来说,约为60MB/s。 您可以使其变慢,但不能更快。

1

如果你想要纯IO速度,你可以尝试使用CreateFileMappingMapViewOfFile。我没有在Windows下测量过这个,但是在Linux下使用类似的技术可以显著提高速度。


-1

没有最快的I/O读取方法。你无法比使用fread或等效方法更快。使用线程也不会有帮助,因为硬盘I/O仍然是主要瓶颈。

当批量读取硬盘中的所有文件时,速度最终取决于硬盘的速度。很可能95%的时间都花在等待I/O上,所以多线程最多只能将速度提高5-6%,但不会使程序运行两倍快。


2
这与我的措施不符(在Linux上完成)。你肯定可以击败fread。即使硬盘IO将是主要瓶颈,分析他提到的某些格式也需要一些CPU,因此使用线程仍然会有所收益。 - James Kanze
1
他的程序会变快一倍吗?还是他会花费巨大的努力将其优化为快5%?在我看来,他(错误地)认为通过使用深奥的函数可以显著加速程序,而事实上,在读取硬盘上的所有文件时,无法超越fread的优化。 - sashoalm
这取决于fread的实现,但通常情况下,加速50%或更多并不罕见。 - James Kanze
1
我不确定你所说的“懒惰读取”是什么意思,但是...我承认结果有些让我惊讶。在大多数Unix系统下,当你打开一个文件时,只要你不寻找,系统就会预读,因此你应该会得到一些隐式并行化(代价是在缓冲区之间进行额外的复制)。当一个文件被映射到内存中时,我认为直到出现页面错误才会进行读取,这会使相关线程停滞(但我没有查看任何最近的Unix源代码来确保)。然而,措施就是措施,使用mmap比使用readfreadstd::ifstream快得多。 - James Kanze
我在十多年前(在Windows NT 3.5上)研究过这个问题,并发现(至少对于软件源文件而言),我的速度似乎主要取决于我执行了多少I/O操作。换句话说,分配足够的内存,然后一次性读入整个文件,比分批读取要快得多,远远快于每次想要新行时愚蠢地调用内置的语言I/O例程。 - T.E.D.
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接