Fabricio Rodriguez
Fabricio Rodriguez

Reputation: 4239

Does async provide performance improvements in this scenario? (.Net Core 2.1 Web API)

I have a .Net Core 2.1 Web API. Many of my controller actions are not async, and I was thinking about making them async. But I was wondering if it would have any performance improvement at all in at least simple scenarios? Take a very basic action as an example:

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

If I were to convert this to:

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

Surely, at least in this very basic example, the two actions would execute in the same period of time? I mean, even if there are two simultaneous calls to the non-async action method, IIS/Kestrel would take on the task of creating a second instance of it to allow both to execute simultaneously? I mean, it's not like because one client has called this API endpoint, now all other clients must wait for it to complete before they can be served, because it's not async?

Upvotes: 0

Views: 2338

Answers (2)

Chris Pratt
Chris Pratt

Reputation: 239290

Async is not about performance, it's about scalability. In fact, you're actually sacrificing raw performance for better scalability, as async has at least some amount of overhead that will cause everything to be at least slightly less performant, even if it's only a matter of nanoseconds.

Async has one purpose: to allow the thread to be returned to the pool if it's idle. Whereas, sync will hold onto the thread, whether it's in a wait-state or not. However, there is no guarantee that the thread will be released or even that it can be released, as async methods often need to do sync work (i.e. CPU-bound) as well that requires active use of the thread.

Where you see real benefit honestly is when you're slammed. In scenarios where your web served would become thread-starved running all sync, you will likely be able to push through a few more requests with async. The degree of the effect is dependent upon not just how slammed the server is but also how slammed all the constituent operations are as well. With your example of a single FirstOrDefault query, for the most part it will likely be near instantaneous. However, if your database instance is being hit with some large/complex queries or simply too many queries to process in a timely manner, then all of a sudden, that simple process might start taking a lot long than normal. That then might start backing up requests in the queue. Async gives you some breathing room.

Long and short, the performance trade-off of using async is usually pretty minimal, and in times where you need it, it can be a life-saver. You could always wait, profile, see if there's a problem first, and then go back and make things async, but it's kind of a headache to go back and rejigger things that aren't async to be async, after the fact. It's almost always better to just go ahead and use async from the start, if there's any async work to be done (I/O).

Also, FWIW, while it's not always strictly the case, with EF Core in particular, there actually is not "sync" access. The non-async methods simply block on the async versions. So, really there's no good excuse to not just go ahead and use the async versions.

Upvotes: 8

GioP
GioP

Reputation: 87

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

Asynchrony is essential for activities that are potentially blocking, such as web access. Access to a web resource sometimes is slow or delayed. If such an activity is blocked in a synchronous process, the entire application must wait. In an asynchronous process, the application can continue with other work that doesn't depend on the web resource until the potentially blocking task finishes.

with async/await you free your application for manage other work

Upvotes: 1

Related Questions