[英]parsing a mmap()-ed file
通过mmap-ed文件解析的最佳(最快)方法是什么? 它包含成对的数据(字符串int),但是我不能认为它们之间有一定数量的空格/制表符/换行符。
假设您已经映射了整个文件(而不是大块的文件,因为那样会使生活变得非常复杂),我将执行以下操作...
// Effectively this wraps the mmaped block
std::istringstream str;
str.rdbuf()->pubsetbuf(<pointer to start of mmaped block>, <size of mmaped block>);
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页内存的解析(理想情况下)为数十微秒。
因此,您不能指望预取器能够跟上步伐,特别是因为它只会在看起来您需要更多时才进行预取(即使假设查找时间为零,由于机械磁盘上的旋转延迟,它实际上也保证了前期成本)。
因此,除非您的总数据只有十几个千字节(在这种情况下,无论如何,如何尽可能快地处理它都是毫无意义的),在开始扫描之前先疯狂(MADV_WILLNEED)是有意义的,因此系统不会等着看您的访问模式触发它的启发式方法,而是顺序地读取它可以不间断地读取的内容。 一旦超过访问时间,磁盘带宽(顺序)就很大。 您可能仍然会追上来,但要晚得多。 如果您的数据集足够大,因此可能不适合放入RAM,则对时不时看到的数据调用MADV_DONTNEED是一个好主意。
对于页面错误,也适用于高速缓存未命中。 缓存的负载为1-2个周期,内存的负载为200-500个周期。
CPU具有针对顺序访问模式的自动预取功能,但是受到限制。
首先,预取永远不会跨越页面边界。 那是因为如果是这种情况,那么自动预取将有规律地触发页面错误,这将是非常不愉快的。
其次,仅在连续两次未命中之后才进行预取,这是为了确保仅在可能有意义的情况下才启动预取。 为每个随机读取预取相邻的缓存行将是愚蠢的,因为这会不必要地浪费宝贵的缓存行。
第三,预取需要时间,一旦CPU中的启发式触发器触发,您就已经在争夺数据,因此,早于晚。
幸运的是, 您知道将需要什么数据,并且知道很长时间了。 因此,您可以给出预取提示,这将为CPU提供宝贵的开始时间(例如,预取半个千字节)。
就目前而言,您的问题太含糊而无法回答。
不过,如果你需要做的是让一些数据出来的文件,你不想做的是使用将在修改内存的方法mmap
编辑区域。
编辑现在,您已经编辑了问题,这更加清楚了。 作为起点,我将使用单个char
指针来遍历整个mmap
ed文件。 提取字符串非常简单(确切的方法取决于您需要对结果执行什么操作),并且可以使用atoi
等人提取整数。
您可以通过std::string
访问它,并使用std::istringstream
以便顺序读取它。 或者使用一些更方便的库,例如,在Qt中,您可以在从映射的内存构造的QByteArray
上使用QTextStream
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.