内存映射文件是否为大缓冲区提供了优势?

时间:2014-12-01 17:10:07

标签: c++ c memory-management mmap large-data

我的程序适用于需要存储在连续内存(几千兆字节)中的大型数据集。使用std::allocator(即mallocnew)分配内存会导致系统停顿,因为大部分虚拟内存被保留,物理内存被填满。

由于程序一次只能处理一小部分,我的问题是如果使用内存映射文件会提供优势(即mmap或Windows等效。)这就是创建一个大的稀疏临时文件并将其映射到虚拟内存。或者是否有另一种技术会改变系统的分页策略,以便一次将较少的页面加载到物理内存中。

我试图避免构建一个一次加载文件部分的流媒体机制,而是依赖于系统的vm分页。

3 个答案:

答案 0 :(得分:5)

是的,mmap拥有潜力可以加快速度。

需要考虑的事项:

  • 请记住,VMM会阻止页面大小被阻止(Linux上为4k)
  • 如果您的内存访问权限随着时间的推移而得到很好的本地化,这将很有效。但是如果你对你的整个文件进行随机访问,你最终会进行大量的搜索和捶打(仍然)。因此,请考虑您的“小部分”是否与文件的本地化位相对应。
  • 对于大型分配,mallocfree无论如何都会mmap使用MAP_ANON。因此,映射文件的内存差异就在于您正在让VMM为您执行I / O.
  • 考虑将madvisemmap一起使用,以帮助VMM更好地进行分页。
  • 当你使用openread时(正如erenon建议的那样,posix_fadvise),你的文件仍然保留在缓冲区中(即它不会被立即写出),除非你也使用O_DIRECT。因此,在这两种情况下,您都依赖内核进行I / O调度。

答案 1 :(得分:3)

如果数据已存在于文件中,则会加快速度,尤其是在非连续情况下。 (在连续的情况下,read获胜)

如果使用openread,请考虑使用posix_fadvise

答案 2 :(得分:2)

这实际上取决于您的mmap()实施。将文件映射到内存有几个优点可以被内核利用:

  • 内核知道mmap()页面的内容已存在于磁盘上。如果它决定驱逐这些页面,它可以省略回写。

  • 减少复制操作:read()操作通常首先将数据读入内核内存,然后将其复制到用户空间。

  • 减少的副本还意味着使用更少的内存来存储来自文件的数据,这意味着更多的内存可用于其他用途,这也可以减少分页。

    这也是,为什么在I / O库中使用大型缓存通常是一个坏主意:现代内核已经缓存他们从磁盘读取的所有,在用户空间中缓存副本意味着可以缓存的数据量实际上减少了。

当然,您还可以避免因缓冲应用程序中未知大小的数据而导致的许多麻烦。但这对您作为程序员来说只是一种便利。

但是,即使内核可以利用这些属性,它也不一定。我的经验是LINUX mmap()一般都很好;然而,在AIX上,我目睹了非常糟糕的mmap()性能。所以,如果你的目标是表现,那就是旧的衡量 - 比较 - 决定支持。