C `mmap()`手动并发预故障/分页
我正在尝试微调C `mmap()`手动并发预故障/分页,c,linux,concurrency,mmap,page-fault,C,Linux,Concurrency,Mmap,Page Fault,我正在尝试微调mmap(),以对可能非常大的文件执行快速写入或读取(通常不是同时执行)。写入和读取在一个过程中基本上是连续的,在以后的过程中可能非常稀疏。无需多次访问内存区域 换言之,可以将其视为具有某种损失的文件传输,并以异步方式进行修复 正如预期的那样,mmap()性能的主要限制似乎是它在大文件上生成的小页面错误的数量。此外,我怀疑Linux内核的页到磁盘的惰性导致了一些性能问题。也就是说,任何最终对mmaped内存执行大量写入的测试程序似乎在执行所有写入操作后需要很长时间才能终止/code
mmap()
,以对可能非常大的文件执行快速写入或读取(通常不是同时执行)。写入和读取在一个过程中基本上是连续的,在以后的过程中可能非常稀疏。无需多次访问内存区域
换言之,可以将其视为具有某种损失的文件传输,并以异步方式进行修复
正如预期的那样,mmap()
性能的主要限制似乎是它在大文件上生成的小页面错误的数量。此外,我怀疑Linux内核的页到磁盘的惰性导致了一些性能问题。也就是说,任何最终对mmap
ed内存执行大量写入的测试程序似乎在执行所有写入操作后需要很长时间才能终止/code>munmap内存
我希望通过在执行几乎连续的访问和分页的同时并发地预故障页面来抵消这些错误的代价,而我不再需要这些页面了。但关于这种方法和我对问题的理解,我有三个主要问题:
MAP\u POPULATE
标志,但这似乎试图将整个文件加载到内存中,这在许多情况下是不可容忍的。此外,这似乎会导致mmap()
调用阻塞,直到预故障完成,这也是不可容忍的。我对手动替代方案的想法是生成一个线程,简单地尝试读取内存中的下一个N
页面以强制预取。但实际上,madvise
和MADV_SEQUENTIAL
可能已经做到了这一点李>
msync()
可用于刷新对磁盘的更改。然而,定期这样做真的有用吗?我的想法是,如果程序经常处于磁盘IO的“空闲”状态,并且能够压缩一些磁盘写回,那么它可能会很有用。而且,内核本身可能比应用程序更好地处理这个问题李>
msync()
调用阻塞了所有磁盘IO,包括到文件系统缓存和原始文件系统的IO,那么在程序终止时使用它来过度刷新整个磁盘缓存也没有多大的动机MAP\u POPULATE
标志,但这似乎试图加载整个文件
进入记忆mmap()
调用阻塞,直到预故障完成
这也是有记录的
哪个
这也是不能容忍的。我对手动替代方案的想法是产生一个
线程只是尝试读取内存中接下来的N页,以强制
预取
除非您最初mmap()
文件与开始访问映射之间存在延迟,否则我不清楚您为什么希望这会带来任何改进
但它可能已经是带有MADV_SEQUENTIAL
的madvise了
事实上,这是真的
如果您想要POSIX兼容性,那么您需要寻找POSIX\u madvise()
。我确实建议您使用这个函数,而不是尝试使用您自己的用户空间替代方案。特别是,如果您使用posix_madvise()
在部分或全部映射区域上断言posix_madvise\u SEQUENTIAL
,则有理由希望内核在需要页面之前先读取以加载页面。此外,如果您建议使用POSIX_MADV_DONTNEED
,那么您可能会根据内核的判断提前同步到磁盘,并减少总体内存使用。如果这个机制有用的话,您还可以通过它传递其他建议
msync()
可用于刷新对磁盘的更改。然而,定期这样做真的有用吗?我的想法是它可能
如果程序经常处于磁盘IO的“空闲”状态,则此选项非常有用
并且可以压缩一些磁盘写回。再说一次
内核可能会比以前更好地处理这个问题
申请可以msync()
支持异步同步,因此不需要I/O空闲。因此,当你确信你完成了一个给定的页面,你可以考虑< COD