如何在C#中清空/刷新Windows READ磁盘缓存?

Pre*_*zel 7 .net c# caching disk flush

如果我试图确定驱动器的读取速度,我可以编写例程来将文件写入文件系统然后再读取这些文件.不幸的是,由于Windows执行磁盘读取缓存,因此无法提供准确的读取速度.

有没有办法在C#/ .Net(或者可能使用Win32 API调用)中刷新驱动器的磁盘读取缓存,以便我可以直接从驱动器读取文件而不缓存它们?

Pre*_*zel 13

康斯坦丁:谢谢!该链接有一个命令行EXE,它执行我正在寻找的测试.

我还在该页面上找到了一个链接到该页面上更有趣的文章(在Word和PDF中):使用.NET的顺序文件编程模式和性能

在本文中,它讨论了未缓冲的文件性能(低,没有读/写缓存 - 只是原始磁盘性能.)

引自文章:

在V2 .NET框架中没有简单的方法来禁用FileStream缓冲.必须直接调用Windows文件系统以获取未缓冲的文件句柄,然后在C#中将结果"包装"在FileStream中,如下所示:

    [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);
Run Code Online (Sandbox Code Playgroud)

使用FILE_FLAG_NO_BUFFERING标志调用CreateFile()会告诉文件系统绕过该文件的所有软件内存缓存.作为FileStream构造函数的第三个参数传递的'true'值表示流应该取得文件句柄的所有权,这意味着当关闭流时文件句柄将自动关闭.在这个hocus-pocus之后,以与任何其他方式相同的方式读取和写入未缓冲的文件流.


小智 11

Fix的响应几乎正确且优于PInvoke. 但它有错误,不起作用......

要打开没有缓存的文件,需要执行以下操作:

const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000;

FileStream file = new FileStream(fileName, fileMode, fileAccess, fileShare, blockSize,
    FileFlagNoBuffering | FileOptions.WriteThrough | fileOptions);
Run Code Online (Sandbox Code Playgroud)

几条规则:

  1. blockSize必须是硬盘驱动器簇大小对齐(大多数时间为4096)
  2. 文件位置更改必须是群集大小对齐
  3. 你不能读/写少于blockSize或阻止不对齐它的大小

并且不要忘记 - 还有HDD缓存(比缓存更慢和更小),你无法关闭它(但有时FileOptions.WriteThrough有助于不缓存写入).使用这些选项,您没有理由进行刷新,但请确保您已正确测试此方法不会减慢速度,以防缓存执行速度变慢.


Con*_*tin 4

为什么要DIY?

如果您只需要确定驱动器速度并且对学习如何从 .NET 刷新 I/O 缓冲区并不真正感兴趣,您可以使用http://research.microsoft.com/barc/Sequential_IO/中的 DiskSpd 实用程序。它具有带或不带缓冲区刷新的随机/顺序模式。

该页面还有一些 I/O 相关的研究报告,您可能会觉得有用。