StreamWriter:(Write + Flush)Async似乎比同步变体慢得多 [英] StreamWriter: (Write+Flush)Async seem much slower then synchronous variants

查看:520
本文介绍了StreamWriter:(Write + Flush)Async似乎比同步变体慢得多的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在我的班级中找到一个IO瓶颈,并且惊奇地发现,向文件写入1000000条消息时,sw.Write("m"); sw.Flush()的速度比await sw.WriteAsync("m"); Await sw.FlushAsync();快20000倍.难道有人知道为什么吗?我敢打赌,StreamWriter的构造函数采用String不会为async用法参数化流.

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.

下面的代码可以从C#交互式启动.是的,它不是测量速度的最佳位置,但无论如何它都会显示出问题所在:

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

通过C#Interactive在我的家用PC上启动,输出为

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

在1毫秒内完成了1000次迭代.

Completed 1000 iterations in 1 milliseconds.

用于同步代码和

在43383毫秒内完成了1000次迭代.

Completed 1000 iterations in 43383 milliseconds.

用于异步.

更新 :另外,我注意到该程序在FlushAsync内部运行速度变慢. WriteAsync的运行速度几乎与同步版本相同.

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

欢迎所有评论.

更新2 * :正如@Cory Nelson在他的答案的评论中提到的那样,FileStream.FlushAsync是用Task.Factory.StartNew实现的伪造的async,因此除了开销之外,没有任何用处.与正在执行的工作相比,处理短消息时,开销变得足够大,从而降低了执行速度.

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.

推荐答案

StreamWriter不会以异步模式打开其基础流.这可能会导致性能下降.如果要将其用于异步,则应打开自己的Stream:

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?

异步确实具有一定的固定数量的内存和GC开销,并且具有如此短暂的操作-尤其是因为StreamWriter.WriteAsync当前尚未针对小写操作进行优化-您必然会看到更多的开销.常见用法.

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.

这篇关于StreamWriter:(Write + Flush)Async似乎比同步变体慢得多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆