通过预填充ifstream缓冲区来加速多次查找

时间:2019-02-28 00:53:08

标签: c++ filestream seek

我想以已知的偏移量(例如8G)在巨大文件(〜10G)的1G连续区域中加快成千上万的搜索和读取。即该模式看起来像:seek(8.00G), read(128 bytes), seek(8.01G), read(56 bytes),然后是

基本伪代码-方法1

int known_offset = 8*1024*1024;
std::ifstream fs("fname", std::ios_base::in | std::ios_base::binary)
for(int i = 0; i < 1000; i++) {
    fs->seekg(known_offset, std::ios::beg);
    fs->read(buf, 128);
    known_offset += calculate_fwd_offset_based_on_buf(buf)
}

可能的改进-方法2
我考虑过增加ifstream读取缓冲区的大小,以便它预取并填充缓冲区,以便以下查找使用该缓冲区来避免/减少磁盘查找。类似于:

char buf[8*1024*1024];
std::ifstream fs("fname", std::ios_base::in | std::ios_base::binary)
fs.rdbuf()->pubsetbuf(buf, 8*1024*1024);
// Remaining code remains same

现在,我对方法(1)和(2)的方法运行了strace/time命令。方法(2)花费的时间更长,并且在情况(2)中发生较大读取时,两次发生的LSEEK / read调用次数完全相同,这是我猜测为什么需要更长的时间。有什么方法可以使seekg/read正常工作?

不便的解决方案
通过删除seekg(next_offset)并改为执行fs.read(buf, num_chars_to_next_offset),可以使上述方法起作用。这将读取次数从9000减少到〜40。我真的更喜欢它对搜索有效,因为我不必要地通过这种方式将字符复制到noop缓冲区中。

0 个答案:

没有答案