【问题标题】:Do nested async/await calls give any performance boost?嵌套的 async/await 调用是否会提高性能?
【发布时间】:2021-08-29 14:35:39
【问题描述】:

这与 Why use Async/await all the way down 有点相关。我有一些需要维护的旧版 EF Core,其中包含许多非异步的嵌套调用。我想知道是否可以使顶级控制器仅异步并使用 Task.Run() 包装服务调用。

这两个控制器动作有什么区别。 在第一个中,EF 核心被同步调用。但是电话 包装在 Task.Run 中,所以我假设它将异步执行

第二个,EF核心调用是异步的 但是,由于控制器操作是异步的,这甚至是必要的吗? async inside async inside async... 是否会比顶部的一个异步调用提供任何性能提升?

案例一

    //controller, async call
    public async Task<ActionList<string>> GetNames()
    {
        var names = await Task.Run(() => peopleService.GetNames());
        return Ok(names);
    }

//people service layer, no async
public List<string> GetNames()
{
    return _context.People.Where(...).Select(x => x.Name).ToList();
}

案例2

//controller, async
public async Task<ActionList<string>> GetNames()
{
    var names = await  peopleService.GetNames();
    return Ok(names);
}

//people service layer, async
public async Task<List<string>> GetNamesAsync()
{
    return await _context.People.Where(...).Select(x => x.Name).ToListAsync();
}

【问题讨论】:

    标签: entity-framework asp.net-core async-await


    【解决方案1】:

    Task.Run 仅用于在线程池上运行您的代码。这对于 WPF 或 WinForms 应用程序很有用,因为它释放了 UI 线程以继续处理其他 UI 事件。但是,它不会在 ASP.NET 中带来任何性能优势,因为您只是将执行从一个线程池线程切换到另一个线程池线程。当遇到 EF ToList 调用时,该线程池线程将被阻塞。如果你有很多并发请求,线程池将被耗尽。 .NET 有一个线程注入策略,但这是有限的,所以一些请求会超时。如果您的负载变得非常高,您将需要如此多的线程,从而耗尽您的系统资源(CPU 和内存)。

    相比之下,async-all-the-way 意味着您在数据库 I/O 操作正在进行时永远不会阻塞任何线程。每个异步操作都由底层系统处理,只有在操作完成后才会在线程池上恢复执行。这使您的系统可以扩展到更大数量的并发请求。

    【讨论】:

    • 对于数据库调用,您通常会在 .NET 线程池大小成为问题之前很久就耗尽数据库服务器上的资源(或达到保护性连接池大小限制)。所以使用异步数据库访问调用通常不会提高系统的整体可伸缩性。使用异步可能会从线程堆栈中节省 50MB 的内存。
    • 没有争论,只是注意到对系统可扩展性的总体影响通常很小。
    • @DavidBrowne-Microsoft:我不会这么说,即使对于传统的 SQL Server 后端也是如此。线程池最初只包含少量线程,通常对应于内核数。线程池可以注入新线程,但只能在任务完成时或以 500 毫秒的间隔注入。因此,如果您的数据库操作往返时间超过 500 毫秒,您将开始遇到线程池不足的情况,因为并发操作少至 8 或 16 个,这远低于 SQL Server 的可伸缩性限制。
    • @DavidBrowne-Microsoft:.NET 每 500 毫秒只注入一个线程。如果您突然收到大量请求,其中大部分将由于线程池饥饿而超时。此外,线程的轻量级不足以扩展至这种程度。在 64 位系统上,每个线程都需要一个 4MB 的堆栈。阅读 Microsoft 在 thread injectionmore recent analysis 上的(旧)文章。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 2012-12-14
    • 2018-06-02
    相关资源
    最近更新 更多