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

发布于 2024-07-05 03:54:53 字数 179 浏览 7 评论 0原文

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

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

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.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

咋地 2024-07-12 03:54:53

康斯坦丁:谢谢! 该链接有一个命令行 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,未缓冲的文件
流的读取和写入相同
与其他方式一样。

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

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

EDIT 2024: It seems that Microsoft has taken down the original page. Here is a link to the Wayback machine copy of it: https://web.archive.org/web/20150328142042/http://research.microsoft.com/apps/pubs/default.aspx?id=64538

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#:

    [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.

漫雪独思 2024-07-12 03:54:53
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);
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);
能怎样 2024-07-12 03:54:53

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

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

忆伤 2024-07-12 03:54:53

为什么要 DIY?

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

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

Why 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.

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

冧九 2024-07-12 03:54:53

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 缓存(比操作系统缓存更慢且更小),您可以' t 关闭(但有时 FileOptions.WriteThrough 有助于不缓存写入)。 使用这些选项,您没有理由刷新,但请确保您已经正确测试了这种方法不会减慢速度,以防您的缓存实现速度较慢。

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文