如果我试图确定驱动器的读取速度,我可以编写一个例程来将文件写入文件系统,然后将这些文件读回。不幸的是,这并不能提供准确的读取速度,因为 Windows 会进行磁盘读取缓存。
有没有办法在 C# / .Net 中刷新驱动器的磁盘读取缓存(或者可能使用 Win32 API 调用),以便我可以直接从驱动器读取文件而不缓存它们?
康斯坦丁:谢谢!该链接有一个命令行 EXE,它执行我正在寻找的测试。
我还在该页面上找到了一个链接,指向该页面上更有趣的文章(Word 和 PDF):Sequential File Programming Patterns and Performance with .NET
在本文中,它讨论了无缓冲文件性能(iow,没有读/写缓存——只是原始磁盘性能。)
直接引用文章:
在 V2 .NET 框架中没有简单的方法来禁用 FileStream 缓冲。必须直接调用 Windows 文件系统以获取未缓冲的文件句柄,然后将结果“包装”在 FileStream 中,如下所示在 C# 中:
[DllImport("kernel32", SetLastError=true)]
static extern unsafe SafeFileHandle CreateFile(
string FileName, // file name
uint DesiredAccess, // access mode
uint ShareMode, // share mode
IntPtr SecurityAttributes, // Security Attr
uint CreationDisposition, // how to create
uint FlagsAndAttributes, // file attributes
SafeFileHandle hTemplate // template file
);
SafeFileHandle handle = CreateFile(FileName,
FileAccess.Read,
FileShare.None,
IntPtr.Zero,
FileMode.Open,
FILE_FLAG_NO_BUFFERING,
null);
FileStream stream = new FileStream(handle,
FileAccess.Read,
true,
4096);
使用 FILE_FLAG_NO_BUFFERING 标志调用 CreateFile() 会告诉文件系统绕过文件的所有软件内存缓存。作为第三个参数传递给 FileStream 构造函数的 'true' 值表明流应该拥有文件句柄的所有权,这意味着当流关闭时文件句柄将自动关闭。在这个 hocus-pocus 之后,以与任何其他方式相同的方式读取和写入未缓冲的文件流。
Fix 的响应几乎是正确的,并且比 PInvoke 更好。 但是它有错误并且不起作用......
要打开不带缓存的文件,需要执行以下操作:
const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000;
FileStream file = new FileStream(fileName, fileMode, fileAccess, fileShare, blockSize,
FileFlagNoBuffering | FileOptions.WriteThrough | fileOptions);
几条规则:
并且不要忘记 - 还有 HDD 缓存(它比 OS 缓存更慢且更小),您无法关闭它(但有时 FileOptions.WriteThrough 有助于不缓存写入)。使用这些选项,您没有理由刷新,但请确保您已经正确测试过这种方法不会减慢速度,以防您的缓存实现速度较慢。
为什么要DIY?
如果您只需要确定驱动器速度并且对学习如何从 .NET 刷新 I/O 缓冲区并不真正感兴趣,您可以只使用http://research.microsoft.com/barc/Sequential_IO/中的 DiskSpd 实用程序。它具有带和不带缓冲区刷新的随机/顺序模式。
该页面还包含一些您可能会发现有用的 I/O 相关研究报告。
const int FILE_FLAG_NO_BUFFERING = 0x20000000;
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read,64 * 1024,
(FileOptions)FILE_FLAG_NO_BUFFERING | FileOptions.Asynchronous
& FileOptions.SequentialScan);
我找到了这篇文章,这似乎是一个复杂的程序,因为您还必须刷新其他缓存。