为什么异步单个任务比正常的单个任务运行得更快?

时间:2015-07-25 07:29:52

标签: c# multithreading performance asynchronous

我有一个方法只有一个任务要做,必须等待该任务完成:

public async Task<JsonResult> GetAllAsync()
{
    var result = await this.GetAllDBAsync();
    return Json(result, JsonRequestBehavior.AllowGet);
}

public async Task<List<TblSubjectSubset>> GetAllDBAsync()
{
    return await model.TblSubjectSubsets.ToListAsync();
}

它比没有async-await时运行它快得多。 我们知道

  

async和await关键字不会导致其他线程   创建。异步方法不需要多线程,因为异步   方法不会在自己的线程上运行。该方法在当前运行   同步上下文并仅在线程上使用时间   方法是活跃的

根据此链接:https://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_Threads。当我们没有其他线程来处理这项工作时,加快速度的原因是什么?

3 个答案:

答案 0 :(得分:7)

&#34;异步&#34; 意味着&#34;更快。&#34;

&#34;异步&#34;意味着&#34;以在操作期间不需要线程的方式执行其操作,从而允许该线程用于其他工作。&#34;

在这种情况下,您需要测试单个请求。异步请求将&#34; yield&#34;它的线程到ASP.NET线程池...没有其他用途,因为没有其他请求。

我完全希望异步处理程序比同步处理程序运行更慢。这有多种原因:async / await状态机的开销,以及任务完成以使其线程进入请求上下文时的额外工作。除此之外,Win32 API层仍然针对同步调用进行了大量优化(预计这将在未来十年左右逐渐发生变化)。

那么,为什么要使用异步处理程序?

出于可扩展性原因。

考虑一个服务于多个请求的ASP.NET服务器 - 数百或数千个请求而不是单个请求。在那个的情况下,ASP.NET将非常感谢在请求处理期间返回给它的线程。它可以立即使用该线程来处理其他请求。异步请求允许ASP.NET以更少的线程处理更多请求。

这假设您的后端可以扩展,当然。如果每个请求都必须命中一个SQL Server,那么您的可伸缩性瓶颈可能就是您的数据库,而不是您的Web服务器。

但是,如果您的情况需要它,异步代码可以极大地提高您的Web服务器可伸缩性。

有关详细信息,请参阅我在async ASP.NET上的文章。

答案 1 :(得分:3)

当他提到应用程序架构中涉及的开销时,我同意Orbittman的看法。它不能成为一个非常好的基准测试前提,因为你不能确定降级是否真的可以归结为异步和非异步调用。

我已经创建了一个非常简单的基准测试,以便在异步和同步调用之间进行粗略比较,并且async在实际的整体时间中每次丢失,尽管数据收集部分似乎总是相同。看看:https://gist.github.com/mattGuima/25cb7893616d6baaf970

话虽如此,关于架构的相同想法也适用。框架以不同方式处理异步调用: Async and await - difference between console, Windows Forms and ASP.NET

要记住的主要事情是永远不要将异步与性能增益混淆,因为它完全不相关,并且通常根本不会产生任何增益,特别是使用CPU绑定代码。相反,请查看并行库。

答案 2 :(得分:2)

Async await不是某些人认为的灵丹妙药,在你的例子中并不是必需的。如果您在收到之后正在处理等待操作的结果,那么您将能够返回任务并继续调用线程。然后,您不必等待其余操作完成。在上面的代码中删除async / await是正确的。

在没有看到调用代码的情况下回答问题是不可能的,因为它取决于上下文试图对响应做什么。你得到的不仅仅是一个任务,而是一个在完成后将继续的方法上下文中的任务。有关async / await内部工作原理的更多信息,请参阅http://codeblog.jonskeet.uk/category/eduasync/

最后,我会质疑你的时间,就像对数据库的Ajax请求,以及其他具有潜在更大延迟的区域,例如HTTP请求和响应以及数据库连接本身。我假设您正在使用ORM,而这可能会导致开销。我想知道是不是async / await就是问题。