我试图在班上找到一个IO瓶颈,并且惊讶地注意到,当向文件写入1000000条消息时,sw.Write("m"); sw.Flush()
可以比await sw.WriteAsync("m"); Await sw.FlushAsync();
快20000倍。有没有人知道为什么?我的赌注是StreamWriter
的构造函数使用String
不会对async
用法的流进行参数化。
以下代码可以从C#interactive启动。是的,它不是测量速度的最佳位置,但无论如何它都会显示出来的事情:
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();
从C#Interactive在家用电脑上启动输出
在1毫秒内完成1000次迭代。
表示同步代码和
在43383毫秒内完成了1000次迭代。
用于异步。
更新 :我也注意到程序在FlushAsync
内变慢了。 WriteAsync
几乎与同步版本的速度相同。
欢迎所有评论。
更新2 * :正如@Cory Nelson在评论中提到的那样,FileStream.FlushAsync
是假的async
,是Task.Factory.StartNew
实现的,所以它没有任何有用但有用的开销使用短消息时,与正在完成的工作相比,开销变得足够大,从而减慢了执行速度。
答案 0 :(得分:5)
StreamWriter
,在给定文件路径时,不会以异步模式打开其基础流。这可能会导致性能下降。如果您要将其用于异步,则应该打开自己的Stream
:
Stream s = new FileStream("G:\\file.file", FileMode.Create, FileAccess.Write,
FileShare.None, 4096,
FileOptions.Asynchronous | FileOptions.SequentialScan);
StreamWriter sr = new StreamWriter(s);
需要注意的是,您的基准测试似乎并未捕获实际使用情况。你真的在写每个字符串并在每个字符串之后刷新吗?
Async确实有一定数量的内存和GC开销,并且具有如此短暂的操作 - 特别是当StreamWriter.WriteAsync
目前没有针对小写进行优化时 - 你必然会看到比更常见的用法。