首页 > 解决方案 > 为什么阅读要花这么多时间?

问题描述

我有这个简单的 C++ 代码,用于将图像加载到缓冲区中。

FILE *f = fopen("myimage.jpg", "rb");
fseek(f,0,SEEK_END);
unsigned long fsize = ftell(f);
rewind(f);
unsigned char *buf = new unsinged char[size];
fread(buf, 1, fsize, f);
fclose(f);

我使用 HDD 中约 1MB 的大文件进行测试,执行时间通常在 100 - 200 毫秒之间。这对我来说似乎太多了。我已经对我的 HDD 进行了基准测试,读取速度约为 80 MB/s。这意味着读取 1MB 文件需要 1000/80 = 12.5 毫秒,对吧?真的可以在这样的时间读取文件吗?我的代码有什么问题吗?

标签: c++iohard-drive

解决方案


对于硬盘驱动器,以下是一些必需的操作:

  1. 使驱动器达到适当的速度(又名 5400 转/秒)。
  2. 读取目录(驱动器可能已经缓存了这个)。
  3. 在目录中搜索起始轨道和扇区。
  4. 将磁头定位到正确的轨道。
  5. 等待该部门的到来。
  6. 从扇区中读取位。
  7. {optional} 将磁头重新定位到下一个数据块(扇区和轨道)
  8. 阅读更多数据。
  9. 这些位必须从硬盘驱动器传输到平台上的内存。可能会有等待时间,因为地址总线和数据总线与许多设备共享。

对于 SSD 驱动器,您可以跳过等待盘片加速和等待扇区出现的部分。扇区的位置是通过数学计算的。无需重新定位读取头。

以上这些都需要时间。

其中一个障碍是必须重新定位硬盘驱动器的磁头以读取另一个扇区。连续扇区的开销低于碎片扇区。

编辑 1:提高性能
您可以通过购买具有更快转速和更大缓存的硬盘来提高读取性能。

您可以使用对硬盘进行碎片整理的应用程序。这减少了将磁头重新定位到下一个块的不同位置的需要。

可能最好的性能优化是保持数据流动。每个事务(又名读取)都有开销。例如,读取 1 字节与读取 1024 字节具有相同的开销,因此 1 读取 1024 字节比读取 1024 字节更有效。

为了跟上数据流动的原则,使用多线程。使用一个读入一个或多个缓冲区的线程。如果一个缓冲区在其他线程完成处理缓冲区之前填满,则读入另一个缓冲区。保持数据流动。

不要在文件中搜索数据,而是使用内存。与其读到换行符,不如将一大块数据读入内存。在内存中搜索换行符。搜索内存总是比搜索硬盘快。

最后,如果您的平台有硬件支持,请使用它。某些平台具有 DMA(直接内存访问)芯片。该芯片可以在不使用 CPU 的情况下从端口读取数据并存储到内存中。这允许您的 CPU 在数据被 DMA 芯片转储到内存时执行指令。同样,块传输将比单字节传输更优化。您必须检查平台上的数据表,以查看您的 I/O 硬件是否具有 DMA 以及处理器是否可以访问它。


推荐阅读