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

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

问题描述:

我正在读取专有的二进制数据文件格式。所述格式基本上报头,数据,size_of_previous_data,报头,数据,size_of_previous_data,报头,数据,size_of_previous_data,...头的 部分包括数据的下一个块的字节数以及后被立即列出其大小数据。标题为256字节,数据通常为〜2MB,size_of_previous_data为32位int。读取大文件的小分离块(C++)

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

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

我已经异型我的代码,并几乎全部时间都花在了的fstream ::阅读()的代码读取size_of_previous_data值。我认为当我这样做时,数据立即被缓冲,所以我的fstream :: read()获得下一个头几乎没有时间。

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

+0

为什么不读一开始的所有文件? RAM的GB通常很好,但搜索GB大小的文件很慢并不令人惊讶 – user463035818

+0

如果数据的大小已经存储在头中,那么为什么不在搜索数据时跳过'size_of_previous_data' ?您可以保存读数,直到您需要读取数据本身,然后将其用作一种校验和。如果您一次只读取256个字节,则不需要比此更大的缓冲区。 –

+1

如果您的操作系统支持它,请尝试使用内存映射文件。操作系统将为您处理将块读入内存。 –

假设磁盘查找大约需要10 ms(来自Latency Numbers Every Programmer Should Know),则您的文件为11 GB,由2 MB块组成,理论最小运行时间为5500 * 10 ms = 55秒。

如果您在幅度上的顺序是已经,加快这件事的最有效的方式可能是购买一个SSD。

+0

*假设磁盘查找需要大约10毫秒*这实际上非常乐观。 7,200 RPM SATA磁盘通常在15 ms范围内,而5,400 RPM磁盘可以超过20 ms。但我想知道磁盘的带宽。 70毫秒内的2 MB仅为28 MB /秒。即使假设70 ms中的20 ms是寻道时间,这意味着磁盘只能移动40 MB /秒。这很低,并且数据路径上可能还存在其他硬件瓶颈,这意味着SSD无济于事。 –

+0

如果我正确理解了这个问题,只需要读取256个字节来构建索引,而不是完整的2 MB。那么寻求时间成为瓶颈,而不是带宽。 – Thomas