FileStream.BeginWrite相比于FileStream.Write有哪些优势?

6
我需要在同一文件的不同位置批量写入数据。我希望以最佳性能实现此操作,因此已查看了同步的FileStream.Write和异步的FileStream.BeginWrite方法。
同步的实现很简单,只需在循环中调用所需次数的FileStream.Write即可。异步版本在循环中调用FileStream.BeginWrite,然后执行WaitHandle.WaitAll以阻止,直到它们全部完成。令人惊讶的是,这比简单的同步版本运行得更慢。
我已使用正确的构造函数创建了FileStream,因此可以请求异步操作,并且还测试了IAsyncResult.CompletedSynchronous属性,结果为False,因此它们确实以异步方式运行。除了不阻塞线程进行写操作之外,使用异步版本还有什么意义吗?
以下是我用于测试异步方法的代码,也许有明显的错误?
        // 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();

你为什么需要进行多个BeginWrite调用? - cwharris
我的实际代码需要写入文件的不同部分,因此每个部分实际上都需要寻找不同的位置然后进行写入。 - Phil Wright
1个回答

20

在Windows中,文件写入得到了大力优化。实际上你并不是把数据直接写入磁盘,而是写入文件系统缓存。内存到内存的复制速度可以达到每秒5GB或更快。数据从缓存中被延迟写入磁盘,这样可以优化以减少写头的移动次数。

异步写入是很难进行优化的。虽然确实会花费较长时间,但需要调用线程池线程来进行回调。异步的好处在于最小化主线程的延迟,而不是真正使其更加高效。只有在写入非常大量的数据时才能真正获得它的好处。超出缓存空间大小的量时,写入性能将从每秒5GB降至不到50MB/秒,因为缓存空间只能以磁盘写入的速度来释放。

准确预测它何时发生是很困难的。这取决于机器上的RAM有多少以及其他进程需要使用多少RAM。当写入1GB或更少的数据时,基本上不需要担心它。同时,当异步写入操作正在等待完成时需要确保有其他有用的任务来执行,否则使用异步写入操作就没有意义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接