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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/122362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 14:34:44  来源:igfitidea点击:

How to empty/flush Windows READ disk cache in C#?

提问by Pretzel

If I am trying to determine the read speed of a drive, I can code a routine to write files to a filesystem and then read those files back. Unfortunately, this doesn't give an accurate read speed because Windows does disk read caching.

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

Is there a way to flush the disk read cache of a drive in C# / .Net (or perhaps with Win32 API calls) so that I can read the files directly from the drive without them being cached?

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

采纳答案by Constantin

Why DIY?

为什么要DIY?

If you only need to determine drive speed and not really interested in learning how to flush I/O buffers from .NET, you may just use DiskSpd utility from http://research.microsoft.com/barc/Sequential_IO/. It has random/sequential modes with and without buffer flushing.

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

The page also has some I/O related research reports you might find useful.

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

回答by dbrien

I found thisarticle and it seems that this is a complicated program because you also have to flush other caches.

我找到了这篇文章,似乎这是一个复杂的程序,因为您还必须刷新其他缓存。

回答by Pretzel

Constantin: Thanks! That link has a command-line EXE which does the testing I was looking for.

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

I also found a link off that page to a more interesting article (in Word and PDF) on this page: Sequential File Programming Patterns and Performance with .NET

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

In this article, it talks about Un-buffered File Performance (iow, no read/write caching -- just raw disk performance.)

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

Quoted directly from the article:

直接引用文章:

There is no simple way to disable FileStream buffering in the V2 .NET framework. One must invoke the Windows file system directly to obtain an un-buffered file handle and then ‘wrap' the result in a FileStream as follows in C#:

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

Calling CreateFile() with the FILE_FLAG_NO_BUFFERING flag tells the file system to bypass all software memory caching for the file. The ‘true' value passed as the third argument to the FileStream constructor indicates that the stream should take ownership of the file handle, meaning that the file handle will automatically be closed when the stream is closed. After this hocus-pocus, the un-buffered file stream is read and written in the same way as any other.

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

回答by Fix

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

回答by Mash

Response of Fix was almost right and better than PInvoke. But it has bugsand doesn't works...

Fix 的响应几乎是正确的,并且比 PInvoke 更好。 但是它有错误并且不起作用......

To open up File w/o caching one needs to do following:

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

const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000;

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


Few rules:

几条规则:

  1. blockSize must be hard drive cluster size aligned (4096 most of the time)
  2. file position change must be cluster size aligned
  3. you can't read/write less than blockSize or block not aligned to it's size
  1. blockSize 必须与硬盘驱动器簇大小对齐(大部分时间为 4096)
  2. 文件位置更改必须与簇大小对齐
  3. 你不能读/写小于 blockSize 或块不与它的大小对齐

And don't forget - there is also HDD Cache (which slower and smaller than OS cache) which you can't turn off by that (but sometimes FileOptions.WriteThrough helps for not caching writes). With those options you have no reason for flushing, but make sure you've properly tested that this approach won't slow things down in case your implementation of cache is slower.

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