代码之家  ›  专栏  ›  技术社区  ›  Naveen

硬盘读取的性能问题

  •  4
  • Naveen  · 技术社区  · 15 年前

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

    (1)。OS(在我的例子中是Windows)是否将最近读取的文件缓存到某个位置,以便随后的加载更快?

    (2)。如果我能保证我读到的所有文件都在同一个目录中,那么我有没有办法把它们放在硬盘上,这样我的磁盘访问时间就更快了?

    我能为这个做些什么吗?

    7 回复  |  直到 15 年前
        1
  •  8
  •   Michael    15 年前

    1)Windows在内存中缓存最近读取的文件。这本书 Windows Internals 包括对这项工作方式的出色描述。现代版本的Windows还使用了一种称为Superfetch的技术,该技术将根据使用历史记录和ReadyBoost(可缓存到闪存驱动器)抢先将磁盘内容提取到内存中,从而实现更快的随机访问。所有这些都将提高首次运行后从磁盘访问数据的速度。

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

        2
  •  8
  •   Adrian McCarthy    15 年前

    你编号的问题似乎已经回答了。如果您仍然想知道如何提高硬盘驱动器的读取速度,下面是一些提示:

    • 使用操作系统功能读取(例如, ReadFile )而不是包装库(比如 iostreams stdio )如果可能的话。许多包装机引入了更多的缓冲级别。
    • 按顺序阅读,并让Windows知道您将要按顺序阅读 FILE_FLAG_SEQUENTIAL_SCAN 旗帜。
    • 如果你只想读(而不是写),一定要打开文件来读。
    • 以块读取,而不是字节或字符。
    • 理想情况下,块应该是磁盘集群大小的倍数。
    • 以群集对齐的偏移量读取光盘。
    • 在页面边界读取到内存。(如果您要分配一个大块,它可能是页面对齐的。)
    • 高级:如果您可以在刚开始读取文件之后开始计算,那么您可以使用重叠的I/O来尝试并行计算,并尽可能多地进行后续读取。
        3
  •  3
  •   Jeremy Friesner    15 年前

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

    至于提高磁盘访问速度,您可以尝试对驱动器进行碎片整理,但我不希望它有太多帮助。与RAM访问相比,驱动器访问速度很慢,这就是RAM缓存提供如此快速的原因。

        4
  •  2
  •   Steve Wortham    15 年前

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

    然后用它来确定转移率。然后你可以用这个传输率和你跑步时得到的数据进行比较。 HD Tune . 值得一提的是,我自己运行这个程序,用我的Western Digital RE3驱动器(可用的7200 rpm SATA驱动器之一)获得了44.2 MB/s的最小速度、87 MB/s的平均速度、110 MB/s的最大读取速度。

    所有这些的要点是看您自己的应用程序是否在尽其所能地做得最好。换句话说,除了高速缓存之外,你不能以比硬盘更快的速度读取文件。所以,如果你达到了这个极限,就没有别的事可做了。

        5
  •  2
  •   Andre    15 年前

    另外,确保在测试期间没有耗尽内存。为正在读取的物理驱动器运行perfmon和monitor memory>available bytes和physical disk>disk read bytes/sec。监控过程的I/O也是一个好主意。请记住,后者结合了所有I/O(包括网络)。

    您应该期望从单个平均SATA驱动器进行50 MB/s的顺序读取。一对好的带区串行SCSI驱动器将为您提供大约220 MB/s的内存。如果您看到可用内存接近于零,那将是您的问题。如果在你第一轮阅读后它仍然是平的,那它与你的应用程序有关系。

        6
  •  1
  •   Les    15 年前

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

        7
  •  0
  •   Calyth    15 年前

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

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