ETA:有人认为这是另一个问题的重复,该问题本质上提出了相同的问题,但不幸的是,答案已经过时了。提供编程解决方案的一个答案不适用于 Windows 10。其他答案推荐第三方工具或为 Posix 或 Linux 提供建议。
我正在尝试对读取文件的不同方法进行基准测试,以便了解构建在操作系统接口之上的库层的开销、各种访问模式的影响以及操作系统层是否可用的“提示”提高特定访问模式的吞吐量。
如果您运行读取数据文件的基准测试,然后运行读取同一文件的不同基准测试,则第二个测试通常会快得多,因为大部分或全部文件将位于缓存中。
消除测量中缓存影响的一种方法是在进行测量之前读取一次文件来预热缓存。但我对冷缓存案例感兴趣。
如何测量读取尚未在缓存中的文件的速度?
迄今为止我最好的想法:
有更好的方法吗?有没有办法消除重启?我可以确定重新启动实际上会从缓存中清除测试文件吗?
有人向我指出一个答案,该答案说,只需使用 FILE_FLAG_NO_BUFFERING 打开文件,然后再次关闭它,就可以从 Windows 文件缓存中清除单个文件。这种行为没有记录,但它显然适用于旧版本的 Windows。不幸的是,它在 Windows 10 上对我没有效果。
建议的其他解决方案涉及全局禁用、限制或清除文件缓存,这不是我试图模拟的场景。
我想出的最佳解决方案是让基准测试程序在每次测量之前创建一个新的未缓存测试文件。
CreateFile 与 CREATE_ALWAYS 和 FILE_FLAG_NO_BUFFERING 一起使用。 (FILE_FLAG_WRITE_THROUGH 是不必要的,并且为此目的可能不明智。)
WriteFile写入文件的内容。由于没有系统缓冲区,因此您必须创建一个缓冲区与驱动器的物理扇区大小对齐,并且该缓冲区是物理扇区大小的整数倍。
一些 Win32 API 报告逻辑扇区大小,它可以与物理扇区大小不同,但我相信逻辑大小始终是物理大小的整数倍,所以这很好。对于任何主流 HDD 或 SSD,物理扇区大小几乎肯定是 512 或 4096 字节。
由于虚拟内存系统使用 4096 字节的页面和页面大小的倍数的SetFileInformationByHandle 使用 FileEndOfFileInfo 作为“类”和 FILE_END_OF_FILE_INFO 结构来设置实际大小。
请注意,您不能使用SetFilePointer 和 SetEndOfFile 来设置文件大小。由于文件在没有系统缓冲的情况下打开,因此SetFilePointer 将调整为扇区边界。
CloseHandle 关闭文件。
显然,为每个测量创建一个新文件需要时间,但是比重新启动以清除缓存中的文件所需的时间要少,并且比影响整个系统文件缓存的任何操作都不那么剧烈。