异步在这种情况下是否可以提高性能? (.Net Core 2.1 Web API)

时间:2018-08-02 13:30:15

标签: async-await asp.net-core-webapi asp.net-core-2.1

我有一个.Net Core 2.1 Web API。我的许多控制器动作都不是异步的,我正在考虑使它们异步。但是我想知道,至少在简单的情况下,它是否会根本提高性能?以一个非常基本的操作为例:

// GET: api/People/5
[HttpGet("id")]
public Person GetPerson([FromRoute] int id)
{
    return _context.People.FirstOrDefault(p => p.Id == id);
}

如果我要将其转换为:

// GET: api/People/5
[HttpGet("id")]
public async Task<Person> GetPerson([FromRoute] int id)
{
    return await _context.People.FirstOrDefaultAsync(p => p.Id == id);
}

当然,至少在这个非常基本的示例中,这两个动作将在同一时间段内执行吗?我的意思是,即使有两个同时调用非异步操作方法,IIS / Kestrel也会承担创建它的第二个实例的任务,以允许它们同时执行?我的意思是,这不是因为一个客户端调用了此API端点,现在所有其他客户端必须等待它完成才能提供服务,因为它不是异步的?

2 个答案:

答案 0 :(得分:4)

异步与性能无关,而与可伸缩性有关。实际上,实际上您是在牺牲原始性能以获得更好的可伸缩性,因为异步具有至少一定量的开销,这将导致所有性能至少略微降低,即使仅几纳秒的问题

异步具有一个目的:允许线程在空闲时返回到池中。而无论线程是否处于等待状态,同步都会保留在线程上。但是,不能保证线程将被释放,甚至不能 被释放,因为异步方法通常需要进行同步工作(即CPU绑定),并且还需要主动使用线程。线程。

诚实地看到真正的好处是当您被抨击时。如果您的网络服务在运行所有同步时都变得线程匮乏,那么您可能可以通过异步处理更多请求。影响的程度不仅取决于服务器受到的冲击程度,还取决于所有构成操作的冲击程度。对于单个FirstOrDefault查询的示例,大多数情况下它几乎是瞬时的。但是,如果您的数据库实例受到一些大型/复杂查询或仅仅是太多查询而无法及时处理,那么突然之间,这个简单的过程可能会比正常情况花费很多时间。这样一来,可能会开始备份队列中的请求。异步为您提供了一些喘息的机会。

总之,使用异步的性能折衷通常很小,在需要时,它可以节省生命。您总是可以等待,剖析一下,先看看是否有问题,然后再回过头来使事情异步,但是事后回头重新整理那些不是异步的事情就变得有点头疼。如果要完成任何异步工作(I / O),从一开始就开始使用异步几乎总是更好的选择。

另外,FWIW,尽管并非总是如此,特别是对于EF Core,实际上并不存在“同步”访问。非异步方法只是阻塞异步版本。因此,确实没有什么好借口不只是继续使用异步版本。

答案 1 :(得分:1)

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

  

异步对于可能阻止的活动至关重要,   例如网络访问。有时访问网络资源的速度很慢或   延迟。如果此类活动在同步过程中被阻止,则   整个应用程序必须等待。在异步过程中,   应用程序可以继续进行其他不依赖于   网络资源,直到潜在的阻止任务完成为止。

使用异步/等待您释放您的应用程序以管理其他工作