【问题标题】:Is there a performance benefit to awaiting lots of small Tasks over a large block of synchronous code?在大块同步代码上等待大量小任务是否有性能优势?
【发布时间】:2014-09-11 01:39:32
【问题描述】:

我有一段代码需要运行大约 1000 个实例。我正在使用任务并行库启动 1k 个任务,然后等待它们完成 Await Task.WhenAll。它是一个相当大的纯同步方法集合,涉及许多 Web 请求和套接字连接。

在性能方面,将每个操作(HttpWebRequest.GetResponse、Socket.Connect 等)更改为带有等待(GetResponseAsync、ConnectAsync 等)的异步方法有什么影响?

我想知道由于每个方法调用都是一个任务,它是否能够更好地在多个内核上共享 CPU 负载,尽管内存开销更大。这是正确的还是我的假设是错误的?

【问题讨论】:

  • 尝试并测量... 此外,如果您没有看到 CPU 负载明显低于 100%,那么您不太可能从重写中获得任何好处(假设您的代码不是那种需要有办法轻松启动并等待无限数量的请求)。

标签: c# .net vb.net asynchronous task-parallel-library


【解决方案1】:

很难量化,但如果你真的很喜欢网络 IO,你真的需要去异步。运行同步 IO,您将通过让大量停放的线程等待它们的响应而使 ThreadPool(这是 TPL 运行任务的地方)饿死。

当 ThreadPool 用完线程时,在它决定对压力做出反应之前会有相当长的延迟。它真的可以减慢速度。您应该注意到通过切换到异步 IO 显着提高了性能。

作为一般规则,您花在 ThreadPool 线程(IO 阻塞)上的时间越少越好。 Async 将这个时间保持在绝对最小值。

【讨论】:

  • 听起来我肯定会受益于将主要的阻止程序(网络请求等)转换为异步方法。除了使代码更复杂之外,还有什么缺点吗?我假设了内存开销?
  • @Mick 我认为 GetResponse 是一种同步方法,而 BeginGetResponse/GetResponseAsync 是异步的?那篇文章有点过头了。我不是试图改变请求的完成方式,而是试图决定让获得响应的部分在新任务中运行是否有益,因为那时 TPL 可以决定如何最好地处理 CPU 负载。
【解决方案2】:

我会非常谨慎地做出或接受关于性能的概括性陈述。这是一件棘手的事情,通常涉及很多依赖项。有时并行运行 1000 个东西可能比同步运行相同的 1000 个要慢,有时它可能会快很多,这实际上取决于这 1000 个任务在做什么,这些任务运行的硬件,内存等等等等。等式中有很多变量。

不要过度设计预期性能带来的好处的东西,性能是您经常感到惊讶的事情,更重要的是能够在系统中检测和测量性能,然后进行更改并再次测量该性能。很多时候,为了让系统运行而必须做出的改变可能会令人惊讶。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 2011-12-18
    • 2017-03-04
    相关资源
    最近更新 更多