增加mapped_file_source、对齐方式和页面大小

Boost mapped_file_source, alignment and page size

本文关键字:方式 对齐 mapped file source 增加      更新时间:2023-10-16

我试图在性能很重要的上下文中解析一些大小高达几百兆字节的文本文件,所以我使用boost mapped_file_source。解析器希望源以一个空字节终止,所以我想检查文件大小是否是页面大小的整数倍(如果是,则返回较慢的非内存映射方法)。我想我可以用

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

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

如何获取页面大小?或者我应该做其他事情吗?(我需要Windows和Linux的解决方案,如果需要,我愿意编写系统特定的代码,但如果可能的话,我更喜欢可移植的代码。)

最简单的事情似乎是修复解析器,将输入的末尾考虑在内(真的不太离谱)。

下一步:一个重大警告。依赖于映射中的尾部字节(如果有的话)为零是未定义cco:http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html

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

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

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

下面是一个简单的片段:在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) = ''; // voilà, null termination done, safely, quickly and reliably
    std::cout << length << "n";
    std::cout << mf.size() << "n";
}

替代拼写:

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

cco AFAICT它可能会杀死兔子或破坏您的流程。