c++ - 为什么阅读要花这么多时间?
问题描述
我有这个简单的 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 毫秒,对吧?真的可以在这样的时间读取文件吗?我的代码有什么问题吗?
解决方案
对于硬盘驱动器,以下是一些必需的操作:
- 使驱动器达到适当的速度(又名 5400 转/秒)。
- 读取目录(驱动器可能已经缓存了这个)。
- 在目录中搜索起始轨道和扇区。
- 将磁头定位到正确的轨道。
- 等待该部门的到来。
- 从扇区中读取位。
- {optional} 将磁头重新定位到下一个数据块(扇区和轨道)
- 阅读更多数据。
- 这些位必须从硬盘驱动器传输到平台上的内存。可能会有等待时间,因为地址总线和数据总线与许多设备共享。
对于 SSD 驱动器,您可以跳过等待盘片加速和等待扇区出现的部分。扇区的位置是通过数学计算的。无需重新定位读取头。
以上这些都需要时间。
其中一个障碍是必须重新定位硬盘驱动器的磁头以读取另一个扇区。连续扇区的开销低于碎片扇区。
编辑 1:提高性能
您可以通过购买具有更快转速和更大缓存的硬盘来提高读取性能。
您可以使用对硬盘进行碎片整理的应用程序。这减少了将磁头重新定位到下一个块的不同位置的需要。
可能最好的性能优化是保持数据流动。每个事务(又名读取)都有开销。例如,读取 1 字节与读取 1024 字节具有相同的开销,因此 1 读取 1024 字节比读取 1024 字节更有效。
为了跟上数据流动的原则,使用多线程。使用一个读入一个或多个缓冲区的线程。如果一个缓冲区在其他线程完成处理缓冲区之前填满,则读入另一个缓冲区。保持数据流动。
不要在文件中搜索数据,而是使用内存。与其读到换行符,不如将一大块数据读入内存。在内存中搜索换行符。搜索内存总是比搜索硬盘快。
最后,如果您的平台有硬件支持,请使用它。某些平台具有 DMA(直接内存访问)芯片。该芯片可以在不使用 CPU 的情况下从端口读取数据并存储到内存中。这允许您的 CPU 在数据被 DMA 芯片转储到内存时执行指令。同样,块传输将比单字节传输更优化。您必须检查平台上的数据表,以查看您的 I/O 硬件是否具有 DMA 以及处理器是否可以访问它。
推荐阅读
- c# - C# Swashbuckle Annotations - 定义响应标头
- c# - 我无法在 C# 中读取公共数组
- sql - PostgreSQL中没有时间的间隔类型
- postgresql - 引用表“gimnasio_competencia”的给定键没有唯一约束匹配
- windows - Azure 更新管理抛出“由于安装过程中的错误,作业失败”错误
- mysql - 从图书馆 1 或图书馆 2 借了至少一本书的两张桌子之间的唯一学生 ID 计数
- python - 向 Django 中的注释过滤器添加 `unique_on` 约束
- typescript - 如何编写密钥对通用“类型”类型脚本
- data-visualization - 无法在画面中使用生成的字段
- node.js - 如何在heroku云中创建文件夹?