FileStream.BeginWrite优势FileStream.Write?优势、FileStream、BeginWrite、Write

2023-09-03 02:40:51 作者:我们年轻就是资本

我需要一个批次写入到相同的文件,但在该文件中不同的地方。我想有可能的最佳性能等方面都看了同步FileStream.Write和异步FileStream.BeginWrite的方法来实现这一目标。

一个同步的FPGA实现是微不足道,只是简单地调用FileStream.Write的时间在一个循环所需要的数量。异步版本要求FileStream.BeginWrite在一个循环,然后再执行WaitHandle.WaitAll的以阻止,直到他们已经全部完成。令我吃惊的这部作品不是简单的同步版本更慢。

我已经使用了正确的构造函数,因此我可以要求异步操作所创建的的FileStream,我也测试这说明假,所以他们以异步的方式确实操作IAsyncResult.CompletedSynchronous财产。看来,使用BeginWrite唯一的好处是,你没有阻止你的线程同时写操作。除了这样的好处是没有任何一点使用异步版本?

下面是测试code口用于与异步方法打,也许有一个明显的错误?

  //大小的块的写入到文件
        VAR块= 1024 * 64;

        //块写异步数
        VAR销售代表= 32;

        //创建新的文件,并设置长度
        变种FS =新的FileStream(@C:\ testfile.dat
                                FileMode.Create,FileAccess.ReadWrite,
                                FileShare.None,块,真);
        fs.SetLength(块*代表);

        //分配资源
        字节[]字节=新字节[块]
        的WaitHandle []手柄=新的WaitHandle [代表]

        的for(int i = 0; I<代表;我++)
        {
            fs.Seek(块*我,SeekOrigin.Begin);
            把手[I] = fs.BeginWrite(字节,0,块,NULL,NULL).AsyncWaitHandle;
        }

        //等待所有异步操作完成
        WaitHandle.WaitAll的(句柄);

        fs.Flush();
        fs.Close();
 
Begin软件手机版下载 Begin最新版v1.0.0 IT168下载站

解决方案

文件写入的高度优化的Windows中。其实你不写入磁盘,写入到文件系统缓存。内存到内存的复制,速度是每秒或更好的5千兆字节。从缓存中,然后将数据延迟方式写入磁盘。反过来优化,以最小化的写头移动次数。

这几乎是不可能的,以优化与异步写入。这确实需要更长的时间,抓住了线程池的线程进行回调并没有免费的午餐。的异步这里最小化主线程延迟的好处,而不是实际上使之更为高效。你只会得到实际好处,当你写的很大量的数据。超过可放入高速缓存。在这一点上,写PERF将从5 GB /秒的悬崖掉下来比〜50 MB /自缓存空间秒只能在盘可写的速度变得可用较少。

究竟何时发生这种情况是很难predict。这取决于有多少内存的机器有多少的它是需要由其他进程。你根本不用担心它,当你写一个千兆字节或更少。而且重要的是你确实有一些有用的东西时,异步写入正在等待做的是非常重要的。等待它们完成使用它的失败点。

I need to make a batch of writes to the same file but at different places within the file. I want to achieve this with the best performance possible and so have looked at the synchronous FileStream.Write and asynchronous FileStream.BeginWrite methods.

A synchronous implemention is trivial and simply calls the FileStream.Write the required number of times in a loop. The async version calls FileStream.BeginWrite in a loop and then does a WaitHandle.WaitAll in order to block until they have all completed. To my surprise this works slower than the simple synchronous version.

I have created the FileStream using the correct constructor so I can request async operation and I also tested the IAsyncResult.CompletedSynchronous property which indicated False and so they did indeed operate in an async fashion. It seems that the only benefit from using BeginWrite is that you are not blocking your thread whilst the write occurs. Apart from this benefit is there any point in using the async version?

Here is the test code I used for playing with the async method, maybe there is an obvious error?

        // 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();

解决方案

File writes are heavily optimized in Windows. You don't actually write to the disk, you write to the file system cache. A memory-to-memory copy, runs at 5 gigabytes per second or better. From the cache, the data is then lazily written to disk. In turn optimized to minimize the number of write head moves.

This is next to impossible to optimize with asynchronous writes. Which do indeed take longer, grabbing the threadpool thread to make the callback doesn't come for free. The benefit of async here is minimizing the main thread delays, not to actually make it more efficient. You will only actually get the benefit when you write very large amounts of data. More than will fit into the cache. At that point, write perf will fall off a cliff from 5 GB/sec to less than ~50 MB/sec since cache space can only become available at the rate the disk can be written.

Exactly when that happens is hard to predict. It depends how much RAM the machine has and how much of it is needed by other processes. You basically don't worry about it when you write a gigabyte or less. And it is important that you actually have something useful to do when the async write is pending. Waiting for them to complete defeats the point of using it.