如何在C#中清空/清空Windows READ磁盘缓存?
时间:2020-03-06 14:36:44 来源:igfitidea点击:
如果要确定驱动器的读取速度,则可以编写例程以将文件写入文件系统,然后再将这些文件读回。不幸的是,这不能提供准确的读取速度,因为Windows会进行磁盘读取缓存。
有没有一种方法可以刷新C / .Net中驱动器的磁盘读取缓存(或者使用Win32 API调用),以便我可以直接从驱动器中读取文件而无需对其进行缓存?
解决方案
我找到了这篇文章,似乎这是一个复杂的程序,因为我们还必须刷新其他缓存。
为什么要自己动手做?
如果我们只需要确定驱动器速度,而不是真正对学习如何从.NET刷新I / O缓冲区感兴趣,则可以只使用http://research.microsoft.com/barc/Sequential_IO/中的DiskSpd实用程序。它具有带/不带缓冲区刷新的随机/顺序模式。
该页面还包含一些与I / O相关的研究报告,我们可能会发现它们很有用。
康斯坦丁:谢谢!该链接具有一个命令行EXE,可以执行我正在寻找的测试。
我还从该页面下找到了指向该页面上一篇更有趣的文章(Word和PDF)的链接:.NET的顺序文件编程模式和性能。
在本文中,它讨论了非缓冲文件的性能(现在,没有读/写缓存-只是原始磁盘性能。)
直接从文章中引用:
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.
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);
Fix的响应几乎是正确的,并且比PInvoke更好。
但是它有错误并且不起作用...
要打开不带缓存的文件,需要执行以下操作:
const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000; FileStream file = new FileStream(fileName, fileMode, fileAccess, fileShare, blockSize, FileFlagNoBuffering | FileOptions.WriteThrough | fileOptions);
很少有规则:
- blockSize必须与硬盘驱动器群集大小对齐(大多数情况下为4096)
- 文件位置更改必须与簇大小对齐
- 我们读/写的内容不能少于blockSize或者不与其大小对齐的块
并且不要忘了还有HDD Cache(它比OS缓存更慢且更小),因此我们无法将其关闭(但有时FileOptions.WriteThrough有助于不缓存写入)。使用这些选项,我们没有理由进行刷新,但是请确保已正确测试了这种方法不会减慢万一缓存实现的速度。