2

问题描述

我需要从磁盘流式传输大文件。假设文件大于内存容量。此外,假设我正在对数据进行一些计算并且结果足够小以适合内存。作为一个假设的例子,假设我需要计算一个 200GB 文件的 md5sum,并且我需要保证将使用多少内存。

总之:

  • 需要恒定的空间
  • 尽可能快
  • 假设非常大的文件
  • 结果适合记忆

问题

使用常量空间从文件中读取/流式传输数据的最快方法是什么?

我有过的想法

如果文件足够小以适合内存,那么mmap在 POSIX 系统上会非常快,不幸的是这里不是这种情况。mmap使用较小的缓冲区大小来缓冲文件的连续块是否有任何性能优势?将缓冲区向下移动文件的系统调用开销会mmap占主导地位吗?或者我应该使用我读入的固定缓冲区fread吗?

4

3 回答 3

3

我不太确定这mmap会非常快(其中非常快被定义为明显快于fread)。

以前用grep mmap,后来改回了fread。原因之一是稳定性(如果文件在映射时缩小或发生 IO 错误,则 mmap 会发生奇怪的事情)。本页讨论了一些关于此的历史。

您可以将系统上的性能与--mmapgrep 选项进行比较。在我的系统上,200GB 文件的性能差异可以忽略不计,但您的里程可能会有所不同!

简而言之,我会使用fread固定大小的缓冲区。它更容易编码,更容易处理错误,而且几乎肯定会足够快。

于 2009-12-08T00:05:43.623 回答
0

mjv 是对的。您可以使用双缓冲区和重叠 I/O。这样,您的运算和磁盘读取可以同时发生。然后我会分析或堆叠拍摄,以使其尽可能快。幸运的是,它会比 I/O 更快,因此您最终会以最高速度运行 I/O 而不会暂停。然后像文件碎片这样的事情就出现了。

于 2009-12-08T13:52:26.597 回答
0

根据您使用的语言,基于您为其声明特定缓冲区大小的文件的类 C 的 fread() 循环将需要此缓冲区大小,不多不少。

我们通常选择 4 到 128 kBytes 的缓冲区大小,如果有更大的缓冲区,则几乎没有收益。

如果性能非常重要,但收益相对较小(并且冒着重新发明某些东西的风险),可以考虑使用双线程实现,其中一个线程在一组两个缓冲区中读取文件,另一个线程执行一次在其中一个缓冲区中计算顺序方式。以这种方式可以消除磁盘访问延迟。

于 2009-12-07T23:59:37.360 回答