使用内存映射文件读取大文件

时间:2012-03-07 20:58:21

标签: windows memory-management

我看到很多文章都建议不要将大文件映射为mmap文件,这样虚拟地址空间就不会被mmap单独占用。

如果地址空间急剧增加的64位进程如何改变? 如果我需要随机访问文件,是否有理由不立即映射整个文件? (几十GB的文件)

3 个答案:

答案 0 :(得分:6)

在64位上,继续并映射文件。

根据Linux经验,有一点需要考虑:如果访问权限是真正随机的,并且文件比预期缓存在RAM中要大得多(因此再次点击页面的可能性很小)那么它可能是值得的指定MADV_RANDOMmadvise以稳定地停止点击文件页面的累积,并毫无意义地交换其他实际有用的东西。不知道windows equivalent API是什么。

答案 1 :(得分:4)

有理由仔细考虑使用内存映射文件,即使在64位平台上(虚拟地址空间大小也不是问题)。它与(潜在的)错误处理有关。

“常规”读取文件时 - 相应的函数返回值报告任何I / O错误。其余的错误处理取决于你。

OTOH如果在隐式I / O期间出现错误(由于页面错误并尝试将所需文件部分加载到适当的内存页面中) - 错误处理机制取决于操作系统。

在Windows中,错误处理是通过SEH执行的 - 所谓的“结构化异常处理”。异常传播到用户模式(应用程序的代码),您可以在其中正确处理它。正确的处理要求您使用编译器中的相应异常处理设置进行编译(以保证调用析构函数,如果适用)。

我不知道如何在unix / linux中执行错误处理。

P.S。我不是说不使用内存映射文件。我说小心地这样做

答案 2 :(得分:2)

需要注意的一点是,在创建映射时,内存映射需要大量连续的(虚拟)内存块;在32位系统上,这特别糟糕,因为在加载的系统上,不太可能长时间运行连续的ram,映射将失败。在64位系统上,这更容易,因为64位的上限是......巨大的。

如果您在受控环境中运行代码(例如您自己构建的64位服务器环境,并且知道运行此代码就好了)继续映射整个文件并处理它。

如果您正在尝试编写可以在任何类型的配置上运行的软件中的通用代码,那么您将需要坚持使用较小的分块映射策略。例如,将大文件映射到1GB块的集合,并具有一个抽象层,该抽象层采用读取(偏移)等操作,并在执行操作之前将它们转换为右块中的偏移量。

希望有所帮助。