我的程序适用于需要存储在连续内存(几千兆字节)中的大型数据集。使用std::allocator
(即malloc
或new
)分配内存会导致系统停顿,因为大部分虚拟内存被保留,物理内存被填满。
由于程序一次只能处理一小部分,我的问题是如果使用内存映射文件会提供优势(即mmap
或Windows等效。)这就是创建一个大的稀疏临时文件并将其映射到虚拟内存。或者是否有另一种技术会改变系统的分页策略,以便一次将较少的页面加载到物理内存中。
我试图避免构建一个一次加载文件部分的流媒体机制,而是依赖于系统的vm分页。
答案 0 :(得分:5)
是的,mmap
拥有潜力可以加快速度。
需要考虑的事项:
malloc
和free
无论如何都会mmap
使用MAP_ANON
。因此,映射文件的内存差异就在于您正在让VMM为您执行I / O. madvise
与mmap
一起使用,以帮助VMM更好地进行分页。open
和read
时(正如erenon建议的那样,posix_fadvise
),你的文件仍然保留在缓冲区中(即它不会被立即写出),除非你也使用O_DIRECT
。因此,在这两种情况下,您都依赖内核进行I / O调度。答案 1 :(得分:3)
如果数据已存在于文件中,则会加快速度,尤其是在非连续情况下。 (在连续的情况下,read
获胜)
如果使用open
和read
,请考虑使用posix_fadvise。
答案 2 :(得分:2)
这实际上取决于您的mmap()
实施。将文件映射到内存有几个优点可以被内核利用:
内核知道mmap()
页面的内容已存在于磁盘上。如果它决定驱逐这些页面,它可以省略回写。
减少复制操作:read()
操作通常首先将数据读入内核内存,然后将其复制到用户空间。
减少的副本还意味着使用更少的内存来存储来自文件的数据,这意味着更多的内存可用于其他用途,这也可以减少分页。
这也是,为什么在I / O库中使用大型缓存通常是一个坏主意:现代内核已经缓存他们从磁盘读取的所有,在用户空间中缓存副本意味着可以缓存的数据量实际上减少了。
当然,您还可以避免因缓冲应用程序中未知大小的数据而导致的许多麻烦。但这对您作为程序员来说只是一种便利。
但是,即使内核可以利用这些属性,它也不一定做。我的经验是LINUX mmap()
一般都很好;然而,在AIX上,我目睹了非常糟糕的mmap()
性能。所以,如果你的目标是表现,那就是旧的衡量 - 比较 - 决定支持。