FileStream.BeginWrite优于FileStream.Write?

我需要对同一个文件进行一批写操作,但是在文件中的不同位置。 我希望以最佳性能实现此目的,因此查看了同步FileStream.Write和异步FileStream.BeginWrite方法。

同步实现很简单,只需在循环中调用FileStream.Write所需的次数即可。 异步版本在循环中调用FileStream.BeginWrite,然后执行WaitHandle.WaitAll以阻止它们全部完成。 令我惊讶的是,这比简单的同步版本慢。

我使用正确的构造函数创建了FileStream,因此我可以请求异步操作,并且还测试了指示False的IAsyncResult.CompletedSynchronous属性,因此它们确实以异步方式运行。 似乎使用Be​​ginWrite的唯一好处是你在写入时不会阻塞你的线程。 除了这个好处之外,使用异步版本还有什么意义吗?

这是我用于播放异步方法的测试代码,可能有一个明显的错误?

// Size of a chunk to be written to file var chunk = 1024 * 64; // Number of chunks to write async var reps = 32; // Create new file and set length var fs = new FileStream(@"C:\testfile.dat", FileMode.Create, FileAccess.ReadWrite, FileShare.None, chunk, true); fs.SetLength(chunk * reps); // Allocate resources byte[] bytes = new byte[chunk]; WaitHandle[] handles = new WaitHandle[reps]; for (int i = 0; i < reps; i++) { fs.Seek(chunk * i, SeekOrigin.Begin); handles[i] = fs.BeginWrite(bytes, 0, chunk, null, null).AsyncWaitHandle; } // Wait for all async operations to complete WaitHandle.WaitAll(handles); fs.Flush(); fs.Close(); 

文件写入在Windows中进行了大量优化。 您实际上没有写入磁盘,而是写入文件系统缓存。 内存到内存的副本,以每秒5千兆字节或更高的速度运行。 从缓存中,数据被懒惰地写入磁盘。 反过来优化以最小化写头移动的数量。

这几乎不可能通过异步写入进行优化。 确实需要更长的时间,抓住线程池线程使回调不是免费的。 这里异步的好处是最大限度地减少主线程延迟,而不是实际提高效率。 只有在编写大量数据时才能获得实惠。 不仅适合缓存。 此时,写入perf将从5 GB /秒下降到小于~50 MB /秒的悬崖,因为缓存空间只能以可写入磁盘的速率变为可用。

究竟何时发生这种情况很难预测。 这取决于机器有多少RAM以及其他进程需要多少RAM。 当你写一千兆字节或更少时,你基本上不用担心它。 当异步写入挂起时,实际上有一些有用的事情是很重要的。 等待他们完成失败的使用点。