【问题标题】:Performance issues with hard disk reading硬盘读取的性能问题
【发布时间】:2010-12-02 10:07:10
【问题描述】:

我有一个 C++ 程序,它从硬盘读取文件并对文件中的数据进行一些处理。我正在使用标准 Win32 API 来读取文件。我的问题是这个程序有时非常快,然后突然减慢到之前速度的 1/6。如果我在多次运行中一次又一次地读取相同的文件,那么通常第一次运行将是最慢的。然后它会保持速度,直到我读取其他一些文件集。所以我的明显猜测是分析磁盘访问时间。我使用了 perfmon 实用程序并测量了我的程序的 IO Read Bytes/sec。正如预期的那样,读取的字节数存在巨大差异(约 5 倍)。我的问题是:

(1)。操作系统(在我的例子中是 Windows)是否将最近读取的文件缓存在某处,以便后续加载更快?

(2)。如果我可以保证我读取的所有文件都在同一个目录中,那么有什么方法可以将它们放在硬盘中,以便我的磁盘访问时间更快?

有什么我可以做的吗?

【问题讨论】:

  • 您能否添加一些数字:您读取了多少数据 (MB),有多少可用 RAM 以及您的应用程序为数据使用了多少 RAM?您是在多次运行之间重新启动程序,还是只是在内部释放内存?
  • 这种行为并不令人惊讶——尽管您需要阅读大量文件(或者内存非常有限)才能如此清楚地看到这种效果。迈克尔的回复很好地回答了它。

标签: c++ performance winapi disk


【解决方案1】:

1) Windows 会在内存中缓存最近读取的文件。 Windows Internals 这本书很好地描述了它是如何工作的。现代版本的 Windows 还使用一种称为 SuperFetch 的技术,该技术将尝试根据使用历史记录抢先将磁盘内容提取到内存中,而 ReadyBoost 可以缓存到闪存驱动器,从而实现更快的随机访问。所有这些都将提高初始运行后从磁盘访问数据的速度。

2) 目录实际上不会影响磁盘上的布局。对驱动器进行碎片整理会将文件数据组合在一起。 Windows Vista 启动时会自动对您的磁盘进行碎片整理。理想情况下,您希望进行大量的顺序读取并最小化您的写入。小的随机访问以及与读取交错的写入会严重影响性能。您可以使用Windows Performance Toolkit 来分析您的磁盘访问。

【讨论】:

    【解决方案2】:

    您的编号问题似乎已经得到解答。如果您仍然想知道如何提高硬盘读取速度,这里有一些提示:

    • 如果可能,请使用操作系统函数(例如 ReadFile)而不是包装库(例如 iostreamsstdio)读取。许多包装器引入了更多级别的缓冲。
    • 按顺序读取,并让 Windows 知道您将使用 FILE_FLAG_SEQUENTIAL_SCAN 标志按顺序读取。
    • 如果您只是要读取(而不是写入),请确保打开文件只是为了读取。
    • 按块读取,而不是字节或字符。
    • 理想情况下,块应该是磁盘集群大小的倍数。
    • 以集群对齐的偏移量从光盘读取。
    • 在页面边界读取内存。 (如果您要分配一个大块,它可能是页面对齐的。)
    • 高级:如果您可以在读取文件开头后开始计算,那么您可以使用重叠 I/O 来尝试尽可能并行计算和后续读取。

    【讨论】:

      【解决方案3】:

      是的,Windows(和大多数现代操作系统)将最近读取的文件数据保存在其他未使用的 RAM 中,这样如果在不久的将来再次请求该文件数据,它就已经在 RAM 中可用,并且可以避免磁盘访问。

      就提高磁盘访问速度而言,您可以尝试对驱动器进行碎片整理,但我认为它不会有太大帮助。与 RAM 访问相比,驱动器访问速度较慢,这就是 RAM 缓存提供如此出色加速的原因。

      【讨论】:

      • 谢谢..实际上我已经对驱动器进行了碎片整理。但没什么区别。
      【解决方案4】:

      作为诊断测试,您能否准确测量首次加载所需的时间?

      然后用它来确定传输速率。然后,您可以采用该传输速率并将其与运行 HD Tune 时得到的结果进行比较。值得一提的是,我自己运行它,我的 Western Digital RE3 驱动器(可用的更快的 7200 RPM SATA 驱动器之一)获得了最低 44.2 MB/s、平均 87 MB/s、最高 110 MB/s 的读取速度。

      所有这一切的重点是看看您自己的应用程序是否尽其所能。换句话说,除了缓存之外,您无法真正比​​硬盘驱动器更快地读取文件。所以,如果你达到了这个限制,那么就没有什么可做的了。

      【讨论】:

      • 如果你的读取速度没有 IO 快,请尝试大块读取,使用异步读取方法并考虑使用内存映射文件 IO。
      【解决方案5】:

      另外,请确保您在测试期间没有耗尽内存。运行 perfmon 并监视正在读取的物理驱动器的 Memory > Available Bytes 和 PhysicalDisk > Disk Read Bytes/sec。监控进程的 I/O 也是一个好主意。请记住,后者结合了所有 I/O(包括网络)。

      从单个普通 SATA 驱动器连续读取的速度应该是 50 MB/s。几个好的条带串行 SCSI 驱动器将为您提供大约 220 MB/s。如果您看到可用内存接近于零,那将是您的问题。如果在您进行第一轮阅读后它保持平稳,则说明它与您的应用有关。

      【讨论】:

        【解决方案6】:

        一个名为 contig 的 Microsoft 实用程序可用于对磁盘上的单个文件进行碎片整理或创建新的未碎片整理文件。

        【讨论】:

          【解决方案7】:

          对于疯狂的答案,您可以尝试格式化驱动器,以便将信息放在最快的部分,看看是否有帮助。

          Tom's Hardware 对如何做到这一点进行了审查。

          【讨论】:

            猜你喜欢
            • 2020-01-26
            • 1970-01-01
            • 2010-11-29
            • 1970-01-01
            • 2014-01-10
            • 2017-09-05
            • 2012-07-09
            • 1970-01-01
            • 2013-07-15
            相关资源
            最近更新 更多