为什么阅读要花这么多时间?

问题描述

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

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

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

解决方法

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

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

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

以上所有都需要时间。

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

修改 1:提高性能
您可以通过购买转速更快、缓存更大的硬盘来提高读取性能。

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

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

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

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

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