如何在 C# 中使用 FILE_FLAG_NO_BUFFERING 调用 win32 CreateFile api 禁用磁盘缓存

发布于 2024-12-24 19:47:02 字数 1809 浏览 5 评论 0原文

大家,我每秒有很多文件写入磁盘,我想禁用磁盘缓存以提高性能,我谷歌搜索找到解决方案:win32 CreateFile method with FILE_FLAG_NO_BUFFERING and 如何清空/刷新 Windows READ 磁盘缓存C#?

我编写了一些代码来测试是否可以工作:

const int FILE_FLAG_NO_BUFFERING = unchecked((int)0x20000000);

[DllImport("KERNEL32", SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
static extern SafeFileHandle CreateFile(
      String fileName,
      int desiredAccess,
      System.IO.FileShare shareMode,
      IntPtr              securityAttrs,
      System.IO.FileMode  creationDisposition,
      int                 flagsAndAttributes,
      IntPtr              templateFile);

static void Main(string[] args)
{
    var handler = CreateFile(@"d:\temp.bin", (int)FileAccess.Write, FileShare.None,IntPtr.Zero, FileMode.Create, FILE_FLAG_NO_BUFFERING, IntPtr.Zero);
    var stream = new FileStream(handler, FileAccess.Write, BlockSize);//BlockSize=4096
    byte[] array = Encoding.UTF8.GetBytes("hello,world");
    stream.Write(array, 0, array.Length);
    stream.Close();
}

运行该程序时,应用程序出现异常:IO 操作将不起作用。很可能文件会变得太长或者句柄没有打开以支持同步IO操作

稍后,我找到了这篇文章当您创建带有约束的对象时,您必须确保使用该对象的每个人都了解这些约束,但是我无法完全理解,所以我更改我的代码来测试:

var stream = new FileStream(handler, FileAccess.Write, 4096);
byte[] ioBuffer = new byte[4096];
byte[] array = Encoding.UTF8.GetBytes("hello,world");
Array.Copy(array, ioBuffer, array.Length);
stream.Write(ioBuffer, 0, ioBuffer.Length);
stream.Close();

它运行正常,但我只想“hello,world”字节而不是全部。我尝试将块大小更改为1或其他整数(不是512的倍数)得到相同的错误。i也尝试 win32 WriteFile api 也得到同样的错误。有人可以帮助我吗?

everyone,i have a lot of files write to disk per seconds,i want to disable disk cache to improve performance,i google search find a solution:win32 CreateFile method with FILE_FLAG_NO_BUFFERING and How to empty/flush Windows READ disk cache in C#?.

i write a little of code to test whether can worked:

const int FILE_FLAG_NO_BUFFERING = unchecked((int)0x20000000);

[DllImport("KERNEL32", SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
static extern SafeFileHandle CreateFile(
      String fileName,
      int desiredAccess,
      System.IO.FileShare shareMode,
      IntPtr              securityAttrs,
      System.IO.FileMode  creationDisposition,
      int                 flagsAndAttributes,
      IntPtr              templateFile);

static void Main(string[] args)
{
    var handler = CreateFile(@"d:\temp.bin", (int)FileAccess.Write, FileShare.None,IntPtr.Zero, FileMode.Create, FILE_FLAG_NO_BUFFERING, IntPtr.Zero);
    var stream = new FileStream(handler, FileAccess.Write, BlockSize);//BlockSize=4096
    byte[] array = Encoding.UTF8.GetBytes("hello,world");
    stream.Write(array, 0, array.Length);
    stream.Close();
}

when running this program,the application get exception:IO operation will not work. Most likely the file will become too long or the handle was not opened to support synchronous IO operations

later,i found this article When you create an object with constraints, you have to make sure everybody who uses the object understands those constraints,but i can't fully understand,so i change my code to test:

var stream = new FileStream(handler, FileAccess.Write, 4096);
byte[] ioBuffer = new byte[4096];
byte[] array = Encoding.UTF8.GetBytes("hello,world");
Array.Copy(array, ioBuffer, array.Length);
stream.Write(ioBuffer, 0, ioBuffer.Length);
stream.Close();

it's running ok,but i just want "hello,world" bytes not all.i trying change blocksize to 1 or other integer(not 512 multiple) get same error.i also try win32 WriteFile api also get same error.someone can help me?

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

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

发布评论

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

评论(2

絕版丫頭 2024-12-31 19:47:02

无缓冲模式下的 CreateFile() 函数强加

现在,仅当您在代码中使用缓冲时,才可以通过这种方式改进文件写入。如果您想在不缓冲的情况下写入 10 个字节,那么无缓冲模式将无济于事。

CreateFile() function in No Buffering mode imposes strict requirements on what may and what may not be done. Having a buffer of certain size (multiple of device sector size) is one of them.

Now, you can improve file writes in this way only if you use buffering in your code. If you want to write 10 bytes without buffering, then No Buffering mode won't help you.

许你一世情深 2024-12-31 19:47:02

如果我正确理解您的要求,这就是我首先尝试的:

创建一个队列,其中包含内存中的数据和磁盘上的目标文件的对象。
您首先开始将文件写入内存,然后在另一个线程上开始遍历队列,打开基于 io-completion 端口的文件流句柄(isAsync=True) - 只是不要打开太多文件,因为在某些时候您'由于缓存垃圾等原因,您可能会开始失去性能。您需要进行分析以了解您的系统和 SSD 的最佳数量。

每次打开后,您可以使用异步文件流方法 Begin... 开始将数据从内存写入文件。 isAsync 提出了一些要求,因此这可能不像正常使用文件流那样容易在每个极端情况下工作。

使用另一个线程创建文件并使用异步 API 另一个线程写入文件是否会有任何改进,只有在创建/打开文件可能会阻塞的情况下才可能出现这种情况。 SSD 在内部执行各种操作以保持对数据的快速访问,因此当您开始执行此类极端性能的操作时,SSD 控制器之间可能存在明显差异。如果控制器驱动程序没有很好地实现,操作系统/Windows 也可能会开始感觉缓慢或冻结。硬件基准测试网站并没有真正强调这种特殊的情况(例如,尽快创建 x KB 并将其写入数百万个文件),并且毫无疑问,有些驱动程序比其他驱动程序慢。

If I understood your requirements correctly, this is what I'd try first:

Create a queue with objects that have the data in memory and the target file on the disk.
You start writing the files first just into memory, and then on another thread start going through the queue, opening io-completion port based filestream handles (isAsync=True) - just don't open too many of them as at some point you'll probably start losing perf due to cache trashing etc. You need to profile to see what is optimal amount for your system and ssd's.

After each open, you can use the async filestream methods Begin... to start writing data from memory to the files. the isAsync puts some requirements so this may not be as easy to get working in every corner case as using filestream normally.

Whether there will be any improvement to using another thread to create the files and another to write to them using the async api, that might only be the case if there is a possibility that creating/opening the files would block. SSD's perform various things internally to keep the access to data fast, so when you start doing this sort of extreme performance stuff, there may be pronounced differences between SSD controllers. It's also possible that if the controller drivers aren't well implemented, OS/Windows may start to feel sluggish or freeze. The hardware benchmarks sites do not really stress this particular kind of scenario (eg. create and write x KB into million files asap) and no doubt there's some drivers out there that are slower than others.

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