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

时间:2008-09-23 17:10:41

标签: c# .net caching disk flush

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

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

5 个答案:

答案 0 :(得分:13)

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

我还在此页面上找到了一个链接,指向此页面上更有趣的文章(Word和PDF格式):Sequential File Programming Patterns and Performance with .NET

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

直接引用文章:

  

没有简单的禁用方法   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);
  

使用。调用CreateFile()   FILE_FLAG_NO_BUFFERING标志告诉了   文件系统绕过所有软件   内存缓存文件。该   “真实”价值作为第三个传递   FileStream构造函数的参数   表示该流应该采取   文件句柄的所有权,意思是   文件句柄会   当自动关闭   流已关闭。在这之后   hocus-pocus,未缓冲的文件   流被读取和写入相同   和其他人一样。

答案 1 :(得分:11)

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

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

const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000;

FileStream file = new FileStream(fileName, fileMode, fileAccess, fileShare, blockSize,
    FileFlagNoBuffering | FileOptions.WriteThrough | fileOptions);

几条规则:

  1. blockSize必须是硬盘驱动器群集大小对齐(大多数时间为4096)
  2. 文件位置更改必须是群集大小对齐
  3. 你不能读/写少于blockSize或阻止不对齐它的大小
  4. 并且不要忘记 - 还有硬盘缓存(比缓存更慢和更小),你无法关闭它(但有时FileOptions.WriteThrough有助于不缓存写入)。使用这些选项,您没有理由进行刷新,但请确保您已经正确测试了这种方法在缓存执行速度较慢的情况下不会减慢速度。

答案 2 :(得分:4)

为何选择DIY?

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

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

答案 3 :(得分:3)

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);

答案 4 :(得分:0)

我发现了this文章,看起来这是一个复杂的程序,因为你还需要刷新其他缓存。