如何优化c++二进制文件读取
How to optimize c++ binary file reading?
我有一个复杂的解释器从(有时)多个文件中读取命令(确切的细节超出了范围),但它需要多次迭代这些多个文件(有些可能是GB大小,无法实现良好的缓冲)。
我希望提高从文件中读取每个命令的速度。
我已经使用RDTSC(程序计数器)寄存器对代码进行了微基准测试,足以知道大约80%以上的时间是从文件中读取的。
事情是这样的:生成输入文件的程序实际上比在我的小型解释器中读取文件更快。也就是说,我可以(理论上)将数据生成器链接到解释器并跳过文件,而不是输出文件,但这不应该更快,对吧?
我做错了什么?还是说,写东西的速度(至少)比从文件中读取快2到3倍?
我已经考虑过mmap,但上的一些结果http://lemire.me/blog/archives/2012/06/26/which-is-fastest-read-fread-ifstream-or-mmap/似乎表明它并不比ifstream快。或者mmap在这种情况下会有帮助吗?
详细信息:
到目前为止,我已经尝试添加一个缓冲区,调整参数,删除ifstream缓冲区(在我的测试用例中,这使它慢了6倍),我目前在四处搜索后不知所措。
代码的重要部分如下。它执行以下操作:
- 如果数据留在缓冲区中,则将表单缓冲区复制到memblock(然后在其中使用)
- 如果缓冲区中没有留下数据,请检查文件中还有多少数据,如果超过缓冲区的大小,请复制缓冲区大小的块
-
如果小于文件
//if data in buffer if(leftInBuffer[activefile] > 0) { //cout <<bufferloc[activefile] <<"n"; memcpy(memblock,(buffer[activefile])+bufferloc[activefile],16); bufferloc[activefile]+=16; leftInBuffer[activefile]-=16; } else //buffers blank { //read in block long blockleft = (cfilemax -cfileplace) / 16 ; int read=0; /* slow block starts here */ if(blockleft >= MAXBUFELEMENTS) { currentFile->read((char *)(&(buffer[activefile][0])),16*MAXBUFELEMENTS); leftInBuffer[activefile] = 16*MAXBUFELEMENTS; bufferloc[activefile]=0; read =16*MAXBUFELEMENTS; } else //read in part of the block { currentFile->read((char *)(&(buffer[activefile][0])),16*(blockleft)); leftInBuffer[activefile] = 16*blockleft; bufferloc[activefile]=0; read =16*blockleft; } /* slow block ends here */ memcpy(memblock,(buffer[activefile])+bufferloc[activefile],16); bufferloc[activefile]+=16; leftInBuffer[activefile]-=16; }
编辑:这是在mac上,osx 10.9.5,带有SSD 的i7
解决方案:
如下所述,mmap能够将速度提高约10倍。
(对于其他搜索此内容的人)特别开放:
uint8_t * openMMap(string name, long & size)
{
int m_fd;
struct stat statbuf;
uint8_t * m_ptr_begin;
if ((m_fd = open(name.c_str(), O_RDONLY)) < 0)
{
perror("can't open file for reading");
}
if (fstat(m_fd, &statbuf) < 0)
{
perror("fstat in openMMap failed");
}
if ((m_ptr_begin = (uint8_t *)mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, m_fd, 0)) == MAP_FAILED)
{
perror("mmap in openMMap failed");
}
uint8_t * m_ptr = m_ptr_begin;
size = statbuf.st_size;
return m_ptr;
}
读取者:
uint8_t * mmfile = openMMap("my_file", length);
uint32_t * memblockmm;
memblockmm = (uint32_t *)mmfile; //cast file to uint32 array
uint32_t data = memblockmm[0]; //take int
mmfile +=4; //increment by 4 as I read a 32 bit entry and each entry in mmfile is 8 bits.
这应该是一个评论,但我没有50的声誉来发表评论。
MAXBUFEMENTS的值是多少?根据我的经验,许多较小的读取比一个较大的读取慢得多。如果可能的话,我建议读取整个文件,有些文件可能是GB,但即使一次读取100MB也比100次读取1MB要好。
若这还不够好,下一步可以尝试压缩(zlib)输入文件(由于大小的原因,可能不得不将它们分成块),并在内存中解压缩。这种方法通常比读取未压缩的文件更快。
正如@Tony Jiang所说,试着尝试缓冲区大小,看看这是否有帮助。
试试mmap看看这是否有帮助。
我假设currentFile
是std::ifstream
?使用iostreams
会有一些开销(例如,istream
将自己进行缓冲,为您所做的添加一个额外的层);虽然我预计开销不会很大,但您可以直接使用open(2)和read(2)进行测试。
您应该能够通过dtruss -e
运行代码,以验证read
系统调用需要多长时间。如果这些占用了你的大部分时间,那么你就达到了操作系统和硬件的限制,所以你可以通过管道、mmap'ing或调整缓冲区大小来解决这个问题。如果这些花费的时间比你预期的要少,那么就在你的应用程序逻辑中寻找问题(在每次迭代中不必要的工作等等)
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- uint8_t同一二进制文件的不同十进制值
- C++单个生成文件多个二进制文件
- 尝试将数字写入二进制文件时引发异常
- C++中读/写二进制文件
- 如何忽略某些二进制文件的执行?
- 对在不同二进制文件中创建的对象文件的依赖关系
- 我的 SDL2 程序需要哪些二进制文件,以便它在另一台未安装 SDL2 的计算机中工作