解析mmap() – ed文件

什么是解析mmap-ed文件的最佳(最快)方法? 它包含数据对(字符串int),但我不能在它们之间使用空格/制表符/换行符。

假设你已经整个文件中的mmaped(而不是块 – 因为这会使生活变得非常复杂),我会做类似以下的事情……

// Effectively this wraps the mmaped block std::istringstream str; str.rdbuf()->pubsetbuf(, ); std::string sv; std::string iv; while(str >> sv >> iv) { // do stuff... } 

我觉得应该有用……

警告这是实现定义的行为,请参阅此答案以获得更好的方法。

用空格分隔的解析字符串/整数对(即foo 50 bar 20 baz 123)应该是闪电般快速的。 更重要的因素将是这一点
a)页面实际上在RAM中,而mmap本身并不能保证
b)缓存行位于L1缓存中

虽然默认情况下mmap在顺序访问时已经提前读取,但磁盘访问时间为几十毫秒 ,并且在4k页内存上进行解析(理想情况下)在几十微秒内。
所以,你不能指望预取器跟上步伐,特别是因为它只会在看起来你需要更多时才预取(即使假设寻道时间为零,实际上也可以保证由于机械磁盘上​​的旋转延迟而导致的前期成本)。
因此,除非您的总数据只有十几千字节(在这种情况下,关于如何尽可能快地执行此操作的问题无论如何都是毫无意义的),在您开始扫描之前进行madvise(MAD​​V_WILLNEED)是有意义的,因此操作系统不会等待看到你的访问模式触发它的启发式,而是在不停止的情况下顺序读取它的内容。 一旦超过访问时间,磁盘带宽(顺序)就很大。 你仍然可能会赶上,但很久以后。 如果你的数据集足够大以至于它可能不适合RAM,那么你现在已经看过的数据上调用MADV_DONTNEED是一个好主意。

对于页面错误也是如此,对于缓存未命中也是如此。 来自高速缓存的负载是1-2个周期,来自存储器的负载大约是200-500个周期。
CPU具有自动预取顺序访问模式,但它们是有限的。
首先,页面边界不会发生预取。 那是因为如果是这种情况,那么自动预取将定期触发页面错误,这将是非常不愉快的。
其次,只有在连续两次未命中之后才会进行预取,这是为了确保预取真正只在它可能有意义时启动。 为每个随机读取预取相邻的高速缓存行将是愚蠢的,因为它将不必要地丢弃有价值的高速缓存行。
第三,预取需要时间,一旦CPU中的启发式触发,您就已经在为数据进行竞争,因此比以后更快。
幸运的是, 你知道你想要什么样的数据,而且你知道它需要很长时间。 因此,您可以提供预取提示,这将为CPU提供一个有价值的开端(预取,例如提前半千字节)。

如果最好/最快你意味着最容易编码,那么这是一个罕见的情况,其中被弃用的std::istrstream完全适合该法案; 调用istrstream::istrstream(char const*, std::streamsize)构造函数重载然后从流中提取数据,就像从任何其他std::istream 。 (这不会像std::istringstream那样复制底层内存。)

如果以最佳/最快的方式表示最佳/最快的运行时性能,我认为您无法击败提升 。 精神 。 qi还是一个手写的解析器,虽然前者在我看来会更容易编写和维护(如果你之前从未使用过boost.spirit,那么除了库学习曲线)。

您可以通过std::string访问它并使用std::istringstream以便按顺序读取它。 或者使用一些更方便的库,例如在Qt中,你可以在从mmaped内存构造的QByteArray上使用QTextStream

就目前而言,你的问题太模糊,无法回答。

尽管如此,如果您只需要从文件中获取一些数据,那么您希望使用的方法是修改mmap ed区域中的内存。

编辑现在你编辑了这个问题就更清楚了。 作为一个起点,我将使用单个char指针迭代整个mmap ed文件。 提取字符串非常简单(确切的方法取决于您需要对结果做什么),并且可以使用atoi等提取整数。