我想以已知的偏移量(例如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缓冲区中。