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

Posted

技术标签:

【中文标题】为啥阅读要花这么多时间?【英文标题】:Why does reading take so much time?为什么阅读要花这么多时间? 【发布时间】:2021-07-30 14:12:18 【问题描述】:

我有这个简单的 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 毫秒之间。这对我来说似乎太多了。我已经对我的硬盘进行了基准测试,读取速度约为 80 MB/s。这意味着读取 1MB 文件需要 1000/80 = 12.5 毫秒,对吧?真的可以在这样的时间读取文件吗?我的代码有什么问题吗?

【问题讨论】:

你如何衡量执行时间? 打开/关闭文件和分配内存会产生开销。 你也是打开和关闭文件,需要查阅文件目录,涉及到head seeks。 Visual Studio 中有一个标准分析器,它在每一步都显示自上次以来经过了多少毫秒。使用它来更好地理解您的代码。 这意味着读取 1MB 文件需要 1000/80 = 12.5 毫秒 没有一个硬盘驱动器寻道可能如此多或更长. 【参考方案1】:

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

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

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

以上都需要时间。

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

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

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

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

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

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

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

【讨论】:

只是补充一点细节:如果没有目录已经被缓存,HDD 将需要寻找并读取每个目录,因为它沿着路径向下。所以在 Windows 上C:\Users\MyUser\Documents\myjpg.jpg 必须读取 C:\、Users、MyUser 和 Documents。每个都涉及至少一次头部搜索。此外,许多文件系统会在读取每个目录和文件时更新访问时间戳,虽然这通常会被缓冲以便稍后写出,但有时会干扰读取文件。哦,防病毒应用程序喜欢将读取的每个文件与其必须读取的 AV 数据库进行比较。

以上是关于为啥阅读要花这么多时间?的主要内容,如果未能解决你的问题,请参考以下文章

大数据!一个大学新生开学要花多少钱?各地月均生活费竟差这么多……

为啥 sklearn Pipeline 调用 transform() 的次数比 fit() 多这么多?

为啥打开与我的数据库的连接需要这么长时间?

为啥检查错误的密码比检查正确的密码要花更长的时间?

为啥 dequeue() 占用这么多处理器时间?

为啥“复合层”需要这么多时间?