读取大文件的小分离块(C ++)

时间:2017-10-17 13:40:14

标签: c++ file io binary buffer

我正在阅读专有的二进制数据文件格式。格式基本上是header,data,size_of_previous_data,header,data,size_of_previous_data,header,data,size_of_previous_data,... 标题的一部分包括下一个数据块的字节数以及在数据之后立即列出的大小。标头为256字节,数据通常为~2MB,size_of_previous_data为32位int。

这些文件一般都很大~GB,而且我经常需要在数十个文件中搜索我想要的数据。为了做到这一点,我在我的代码中做的第一件事是每个文件的idex,即只读取标题并记录相关数据的位置(文件和字节数)。我的代码基本上使用fstream :: read()准备好头文件,检查数据大小,使用fstream :: seekg()跳过数据,然后读入size_of_previous_data,然后重复直到我到达文件末尾。

我的问题是这个索引很慢。数据位于我的Windows 10笔记本电脑上的内部7200 rpm硬盘驱动器上,任务管理器显示我的硬盘驱动器使用率已达到最大值,但我的读取速度仅为1.5 MB / s,响应时间通常> 70 ms。我正在使用std :: fstream读取文件,使用fstream :: get()读取头文件,使用fstream :: seekg()移动到下一个头文件。

我已经分析了我的代码,几乎整个时间花在了fstream :: read()代码上来读取size_of_previous_data值。我假设当我这样做时,紧接在此之后的数据被缓冲,所以我的fstream :: read()获取下一个标题几乎没有时间。

所以我想知道是否有办法优化这个?几乎所有缓冲读取中的整个缓冲区都可能被浪费(97%,如果它是8kB缓冲区)。有没有办法缩小它并且它可能是值得的(也许底层的操作系统缓冲区也是一种我无法改变的方式)?

1 个答案:

答案 0 :(得分:1)

假设磁盘搜索大约需要10毫秒(来自Latency Numbers Every Programmer Should Know),您的文件为11 GB,包含2 MB块,理论上最小运行时间为5500 * 10 ms = 55秒。

如果你已经处于这个数量级,那么加快这种速度的最有效方法可能是购买SSD。