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

Posted

技术标签:

【中文标题】内存映射文件是不是为大缓冲区提供优势?【英文标题】:Do memory mapped files provide advantage for large buffers?内存映射文件是否为大缓冲区提供优势? 【发布时间】:2015-01-29 18:19:44 【问题描述】:

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

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

我试图避免构建一次加载文件部分的流式传输机制,而是依赖系统的虚拟机分页。

【问题讨论】:

您在不同部分之间跳跃的频率如何? 这取决于算法(许多不同)。基本上,它们将分为以下几类: - 从头到尾的顺序读取 - 在不同的大段中并行顺序读取 - 大段内的随机访问(例如,在递归深度优先下降期间) - 其他随机访问 【参考方案1】:

是的,mmap潜力来加快速度。

需要考虑的事项:

请记住,VMM 会在页面大小被阻止(Linux 上为 4k)的情况下对内容进行分页和分页 如果您的内存访问随着时间的推移得到很好的本地化,这将运作良好。但是,如果您对整个文件进行随机访问,您最终会遇到很多寻找和颠簸(仍然)。因此,请考虑您的“小部分”是否与文件的本地化位相对应。 对于大分配,mallocfree 无论如何都会使用 mmapMAP_ANON。因此,内存映射文件的区别只是您让 VMM 为您执行 I/O。 考虑使用madvisemmap 来帮助VMM 进行良好的分页。 当您使用openread(另外,正如erenon 建议的那样,posix_fadvise),您的文件仍然保存在缓冲区中(即它不会立即写出),除非您也使用O_DIRECT。因此,在这两种情况下,您都依赖内核进行 I/O 调度。

【讨论】:

【参考方案2】:

如果数据已经在文件中,它会加快速度,尤其是在非顺序情况下。 (在顺序情况下,read 获胜)

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

【讨论】:

【参考方案3】:

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

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

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

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

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

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

然而,即使内核可以利用这些属性,它也不一定这样做。我的经验是LINUXmmap()一般都可以;然而,在 AIX 上,我目睹了非常糟糕的 mmap() 性能。因此,如果您的目标是性能,那就是旧的衡量-比较-决定。

【讨论】:

以上是关于内存映射文件是不是为大缓冲区提供优势?的主要内容,如果未能解决你的问题,请参考以下文章

NIOMappedByteBuffer-内存映射文件 I/O

Posix 共享内存与映射文件

Linux之共享内存shm和内存映射mmap

循环文件映射会降低性能

内存映射文件处理大文件

mmap库:Python内存映射文件操作