提升mapped_file_source,对齐和页面大小

时间:2014-10-28 17:18:05

标签: c++ boost memory-mapped-files

我试图在性能很重要的环境中解析一些大小高达几百兆的文本文件,因此我使用了boost mapped_file_source。解析器期望源以空字节终止,因此我想检查文件大小是否是页面大小的精确倍数(如果是,则返回到较慢的非内存映射方法)。我以为我可以这样做:

if (mf.size() & (mf.alignment() - 1))

但事实证明,一个测试文件大小为20480,对齐方式为65536(在Windows 7,64位),程序崩溃。我认为发生的事情是页面大小实际上小于对齐,所以我的测试不起作用。

如何获取页面大小?或者我还应该做些什么呢? (我需要Windows和Linux的解决方案,如果有必要,愿意编写特定于系统的代码,但如果可能的话,我更愿意使用可移植的代码。)

1 个答案:

答案 0 :(得分:1)

最简单的事情似乎是修复解析器以考虑输入的结尾(实际上并不太离谱)。

接下来:一个大警告。依赖于地图中的尾随字节(如果有)为零未定义¹:http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html

因此,只需使用size + 1映射文件,然后确定性地添加NUL终结符。我认为这不值得进入平台特定/未定义的行为。

事实上,我刚刚了解了boost::iostreams::mapped_file_base::mapmode::priv,它非常适合您的需求:

  

可以写入以私人访问权限打开的文件,但更改不会影响基础文件 [docs]

以下是一个简单的摘录: Live On Coliru

#include <boost/iostreams/device/mapped_file.hpp>
#include <fstream>
#include <iostream>

namespace io = boost::iostreams;

int main() {
    // of course, prefer `stat(1)` or `boost::filesystem::file_size()`, but for exposition:
    std::streamsize const length = std::distance(std::istreambuf_iterator<char>(std::ifstream("main.cpp").rdbuf()), {});

    io::mapped_file mf("main.cpp", io::mapped_file_base::mapmode::priv, length+1);

    *(mf.end()-1) = '\0'; // voilà, null termination done, safely, quickly and reliably

    std::cout << length << "\n";
    std::cout << mf.size() << "\n";
}

替代拼写:

mf.data()[length] = '\0'; // voilà, null termination done, safely, quickly and reliably
*(mf.begin()+length) = 0; // etc.

¹AFAICT它可能会杀死兔子或使你的过程崩溃。