StreamWriter:(Write+Flush)Async 似乎比同步变体慢得多
StreamWriter: (Write+Flush)Async seem much slower then synchronous variants
我试图在我的 class 中找到一个 IO 瓶颈,并且惊奇地注意到 sw.Write("m"); sw.Flush()
可以比 await sw.WriteAsync("m"); Await sw.FlushAsync();
快 20000,当将 1000000 条消息写入一个文件时。有没有人知道为什么?我敢打赌 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 在我的家用 PC 上启动,输出是
Completed 1000 iterations in 1 milliseconds.
用于同步代码和
Completed 1000 iterations in 43383 milliseconds.
对于异步。
Update:我还注意到程序在 FlushAsync
中变慢了。 WriteAsync
工作速度几乎与同步版本相同。
欢迎所有评论。
更新 2*:正如@Cory Nelson 在对他的回答的评论中提到的,FileStream.FlushAsync
是用 [=20 实现的假 async
=],所以除了开销之外,它没有增加任何有用的东西。当处理短消息时,与正在完成的工作相比,开销变得足够大,从而减慢了执行速度。
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);
另外需要注意的是,您的基准测试似乎没有捕获 real-world 使用情况。你真的在写 single-character 个字符串并在每个字符串后刷新吗?
Async 确实有一定数量的内存和 GC 开销,并且有这样的 short-lived 操作——特别是因为 StreamWriter.WriteAsync
目前没有针对小写操作进行优化——你一定会看到比更常见的用法更多的开销。
我试图在我的 class 中找到一个 IO 瓶颈,并且惊奇地注意到 sw.Write("m"); sw.Flush()
可以比 await sw.WriteAsync("m"); Await sw.FlushAsync();
快 20000,当将 1000000 条消息写入一个文件时。有没有人知道为什么?我敢打赌 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 在我的家用 PC 上启动,输出是
Completed 1000 iterations in 1 milliseconds.
用于同步代码和
Completed 1000 iterations in 43383 milliseconds.
对于异步。
Update:我还注意到程序在 FlushAsync
中变慢了。 WriteAsync
工作速度几乎与同步版本相同。
欢迎所有评论。
更新 2*:正如@Cory Nelson 在对他的回答的评论中提到的,FileStream.FlushAsync
是用 [=20 实现的假 async
=],所以除了开销之外,它没有增加任何有用的东西。当处理短消息时,与正在完成的工作相比,开销变得足够大,从而减慢了执行速度。
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);
另外需要注意的是,您的基准测试似乎没有捕获 real-world 使用情况。你真的在写 single-character 个字符串并在每个字符串后刷新吗?
Async 确实有一定数量的内存和 GC 开销,并且有这样的 short-lived 操作——特别是因为 StreamWriter.WriteAsync
目前没有针对小写操作进行优化——你一定会看到比更常见的用法更多的开销。