StreamWriter: (Write+Flush)Async seem much slower then synchronous variants

烈酒焚心 提交于 2019-12-19 04:16:07

问题


I was trying to find an IO bottleneck in my class and surprisingly noticed that sw.Write("m"); sw.Flush() can be 20000 faster then await sw.WriteAsync("m"); Await sw.FlushAsync(); when writing 1000000 messages to a file. Does, by any chance, anyone know why? My bet is StreamWriter's constructor taking a String does not parametrize a stream for async usage.

The code below can be launched from C# interactive. Yes, it's not the best place to measure the speed but it will show the matter at hand anyway:

var sr = new StreamWriter("G:\\file.file");
var N = 1000;
var sw = new Stopwatch();
sw.Start();

for (var i = 0; i < N; ++i)
{
    sr.Write("m"); // or await sr.WriteAsync("m");
    sr.Flush(); // or await sr.FlushAsync("m");
}

sw.Stop();
Console.WriteLine("Completed " + N
    + " iterations in " + sw.ElapsedMilliseconds + " milliseconds.");

sr.Close();

Launched on my home PC from C# Interactive the output is

Completed 1000 iterations in 1 milliseconds.

for synchronous code and

Completed 1000 iterations in 43383 milliseconds.

for asynchronous.

Update: Also I've noticed that the program slows down inside FlushAsync. WriteAsync works nearly at the same speed as the synchronous version.

All comments are welcome.

Update 2*: As @Cory Nelson mentioned in comments to his answer, FileStream.FlushAsync is a fake async that is implemented with Task.Factory.StartNew, so it adds nothing useful but overhead. When working with short messages the overhead becomes large enough compared to the work being done, thus slowing the execution.


回答1:


StreamWriter, when given a file path, does not open its underlying stream in async mode. This is likely contributing to performance loss. If you're going to use it for async, you should be opening your own Stream:

Stream s = new FileStream("G:\\file.file", FileMode.Create, FileAccess.Write,
                          FileShare.None, 4096,
                          FileOptions.Asynchronous | FileOptions.SequentialScan);
StreamWriter sr = new StreamWriter(s);

Something additional to note is that your benchmark doesn't seem to capture real-world usage. Are you really writing single-character strings and flushing after each one?

Async does have a certain fixed amount of memory and GC overhead, and with such short-lived operations -- especially as StreamWriter.WriteAsync is not currently optimized for small writes -- you are bound to see much more overhead than a more common usage.



来源:https://stackoverflow.com/questions/41964095/streamwriter-writeflushasync-seem-much-slower-then-synchronous-variants

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!