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

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

如果我试图确定驱动器的读取速度,我可以编写一个例程来将文件写入文件系统,然后读回这些文件。不幸的是,这并不能提供准确的读取速度,因为 Windows 会进行磁盘读取缓存。

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

c# .net caching disk flush
5个回答
14
投票

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

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

编辑2024:微软似乎已经撤下了原始页面。以下是其 Wayback 机器副本的链接:https://web.archive.org/web/20150328142042/http://research.microsoft.com/apps/pubs/default.aspx?id=64538

在本文中,它讨论了无缓冲文件性能(哦,没有读/写缓存——只有原始磁盘性能。)

直接引用文章:

没有简单的方法来禁用 V2 .NET 中的文件流缓冲 框架。必须调用 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 标志告诉 文件系统绕过所有软件 文件的内存缓存。这 “true”值作为第三个传递 FileStream 构造函数的参数 表示该流应该采取 文件句柄的所有权,含义 文件句柄将 时自动关闭 流已关闭。在这之后 hocus-pocus,非缓冲文件 流的读取和写入相同 与其他方式一样。


13
投票

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. 您无法读取/写入小于块大小或未与其大小对齐的块

不要忘记 - 还有 HDD 缓存(比操作系统缓存更慢且更小),您无法通过它关闭它(但有时 FileOptions.WriteThrough 有助于不缓存写入)。使用这些选项,您没有理由刷新,但请确保您已经正确测试,如果您的缓存实现速度较慢,这种方法不会减慢速度。


4
投票

为什么要DIY?

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

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


4
投票
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);

-1
投票

我找到了this文章,看来这是一个复杂的程序,因为你还必须刷新其他缓存。

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