文件流.BeginWrite优于FileStream.Write

本文关键字:FileStream Write 优于 BeginWrite 文件 | 更新日期: 2023-09-27 18:10:55

我需要对同一文件进行一批写入,但在文件中的不同位置。我希望以最好的性能实现这一点,因此研究了同步FileStream。写和异步FileStream。BeginWrite方法。

同步实现很简单,只调用FileStream。在循环中写入所需的次数。异步版本调用FileStream。BeginWrite在一个循环中,然后做一个WaitHandle。WaitAll来阻塞,直到它们全部完成。令我惊讶的是,这比简单的同步版本要慢。

我已经使用正确的构造函数创建了FileStream,所以我可以请求异步操作,我还测试了IAsyncResult。CompletedSynchronous属性,它指示False,因此它们确实以异步方式操作。似乎使用BeginWrite的唯一好处是,当写入发生时,您不会阻塞线程。除了这个好处之外,使用异步版本还有什么意义吗?

这里是测试代码,我用来玩异步方法,也许有一个明显的错误?

        // 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优于FileStream.Write

Windows对文件写入进行了大量优化。实际上并不是写磁盘,而是写文件系统缓存。内存到内存的副本,运行速度为每秒5gb或更高。然后将数据从缓存中惰性地写入磁盘。依次优化以最小化写头移动的数量。

这几乎不可能通过异步写进行优化。这确实需要更长的时间,抓取线程池线程来进行回调并不是免费的。这里异步的好处是最小化主线程延迟,而不是使它更有效率。只有在写入非常大量的数据时,才能真正获得好处。超过了缓存的容量。此时,写性能将从5gb/秒急剧下降到小于~ 50mb/秒,因为缓存空间只能在磁盘写入速率下可用。

这种情况何时发生很难预测。这取决于机器有多少RAM以及其他进程需要多少RAM。当你写入1gb或更少的数据时,你基本上不用担心这个问题。重要的是,当异步写挂起时,您实际上有一些有用的事情要做。等待它们完成就失去了使用它的意义。