如何确保在运行基准测试之前不缓存文件?

问题描述 投票:0回答:1

ETA:有人认为这是另一个问题的重复,该问题本质上提出了相同的问题,但不幸的是,答案已经过时了。提供编程解决方案的一个答案不适用于 Windows 10。其他答案推荐第三方工具或为 Posix 或 Linux 提供建议。


我正在尝试对读取文件的不同方法进行基准测试,以便了解构建在操作系统接口之上的库层的开销、各种访问模式的影响以及操作系统层是否可用的“提示”提高特定访问模式的吞吐量。

如果您运行读取数据文件的基准测试,然后运行读取同一文件的不同基准测试,则第二个测试通常会快得多,因为大部分或全部文件将位于缓存中。

消除测量中缓存影响的一种方法是在进行测量之前读取一次文件来预热缓存。但我对冷缓存案例感兴趣。

如何测量读取尚未在缓存中的文件的速度?

迄今为止我最好的想法:

  1. 创建一个包含许多测试文件的目录,所有文件大小相同。
  2. 重新启动机器。
  3. 针对不同的测试文件运行每个基准测试。
  4. 使用每个测试文件后再次重新启动机器。

有更好的方法吗?有没有办法消除重启?我可以确定重新启动实际上会从缓存中清除测试文件吗?


  • Windows 10
  • 内存:64 GB
  • 数据文件大小:5 GB(典型)
  • 我不想全局禁用缓存。
  • 数据文件既不是可执行文件也不是DLL,所以我认为我不必担心Superfetch。
  • 我不介意一旦基准测试开始读取文件,驱动程序是否会提前读取并缓冲数据。这就是一个很长时间没有被触及的文件会发生的情况,而这正是我想要模拟的。使用 FILE_FLAG_NO_BUFFERING 不是答案。
  • 我不太关心 HDD 和 SSD 之间的差异。我对各种编程接口的额外成本比绝对速度更感兴趣。
c++ windows winapi caching file-io
1个回答
0
投票

有人向我指出一个答案,该答案说,只需使用 FILE_FLAG_NO_BUFFERING 打开文件,然后再次关闭它,就可以从 Windows 文件缓存中清除单个文件。这种行为没有记录,但它显然适用于旧版本的 Windows。不幸的是,它在 Windows 10 上对我没有效果。

建议的其他解决方案涉及全局禁用、限制或清除文件缓存,这不是我试图模拟的场景。

我想出的最佳解决方案是让基准测试程序在每次测量之前创建一个新的未缓存测试文件。

  1. CreateFile 与 CREATE_ALWAYS 和 FILE_FLAG_NO_BUFFERING 一起使用。 (FILE_FLAG_WRITE_THROUGH 是不必要的,并且为此目的可能不明智。)

  2. 使用

    WriteFile写入文件的内容。由于没有系统缓冲区,因此您必须创建一个缓冲区与驱动器的物理扇区大小对齐,并且该缓冲区是物理扇区大小的整数倍。

    一些 Win32 API 报告

    逻辑扇区大小,它可以与物理扇区大小不同,但我相信逻辑大小始终是物理大小的整数倍,所以这很好。对于任何主流 HDD 或 SSD,物理扇区大小几乎肯定是 512 或 4096 字节。

    由于虚拟内存系统使用 4096 字节的页面和页面大小的倍数的

    分配粒度,因此使用 VirtualAlloc 应该为您提供正确对齐的内存块。

  3. 除非文件大小恰好是扇区大小的倍数,否则您将写入多余的数据来填充文件的末尾。完成写入后,在关闭文件句柄之前,您可以使用

    SetFileInformationByHandle 使用 FileEndOfFileInfo 作为“类”和 FILE_END_OF_FILE_INFO 结构来设置实际大小。

    请注意,您不能使用

    SetFilePointerSetEndOfFile 来设置文件大小。由于文件在没有系统缓冲的情况下打开,因此SetFilePointer 将调整为扇区边界

  4. 使用

    CloseHandle 关闭文件。

此时,该文件应该可用,但不在系统的文件缓存中,因此您可以执行测量。一旦完成,该文件将(可能)最终进入缓存。因此,如果您想进行另一次测量,则必须再次创建一个新的未缓存文件。

显然,为每个测量创建一个新文件需要时间,但是比重新启动以清除缓存中的文件所需的时间要少,并且比影响整个系统文件缓存的任何操作都不那么剧烈。

© www.soinside.com 2019 - 2024. All rights reserved.