2

大家,我每秒有很多文件写入磁盘,我想禁用磁盘缓存以提高性能,我谷歌搜索找到解决方案:win32 CreateFile method with FILE_FLAG_NO_BUFFERING 和How to empty/flush Windows READ disk cache in 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 operation will not work。很可能文件会变得太长或句柄未打开以支持同步 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 倍数)得到相同的错误。我也尝试 win32 WriteFile api 也得到相同的错误。有人可以帮助我?

4

2 回答 2

4

无缓冲模式下的 CreateFile() 函数对可以做什么和不可以做什么提出了严格的要求。具有一定大小的缓冲区(设备扇区大小的倍数)就是其中之一。

现在,只有在代码中使用缓冲时,才能以这种方式改进文件写入。如果你想在不缓冲的情况下写入 10 个字节,那么无缓冲模式对你没有帮助。

于 2012-01-01T10:16:56.363 回答
1

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

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

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

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

于 2014-01-29T16:10:45.350 回答