5

I have a method which has just one task to do and has to wait for that task to complete:

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();
}

It is significantly faster than when I run it without async-await. We know

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active

According to this link: https://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_Threads. What is the reason for being faster when we don't have another thread to handle the job?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hamid Bahmanabady
  • 665
  • 1
  • 8
  • 20

3 Answers3

8

"Asynchronous" does not mean "faster."

"Asynchronous" means "performs its operation in a way that it does not require a thread for the duration of the operation, thus allowing that thread to be used for other work."

In this case, you're testing a single request. The asynchronous request will "yield" its thread to the ASP.NET thread pool... which has no other use for it, since there are no other requests.

I fully expect asynchronous handlers to run slower than synchronous handlers. This is for a variety of reasons: there's the overhead of the async/await state machine, and extra work when the task completes to have its thread enter the request context. Besides this, the Win32 API layer is still heavily optimized for synchronous calls (expect this to change gradually over the next decade or so).

So, why use asynchronous handlers then?

For scalability reasons.

Consider an ASP.NET server that is serving more than one request - hundreds or thousands of requests instead of a single one. In that case, ASP.NET will be very grateful for the thread returned to it during its request processing. It can immediately use that thread to handle other requests. Asynchronous requests allow ASP.NET to handle more requests with fewer threads.

This is assuming your backend can scale, of course. If every request has to hit a single SQL Server, then your scalability bottleneck will probably be your database, not your web server.

But if your situation calls for it, asynchronous code can be a great boost to your web server scalability.

For more information, see my article on async ASP.NET.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • what do you mean about this sentence "performs its operation in a way that it does not require a thread.." if there is no other thread so how it does that operation without using main thread? – Hamid Bahmanabady Jul 26 '15 at 06:33
  • @HamidBahmanabady: I have a [long blog post on that subject](http://blog.stephencleary.com/2013/11/there-is-no-thread.html). – Stephen Cleary Jul 26 '15 at 11:26
  • Hit it right on the head with `for scalability reasons` – Stephen P. Sep 29 '16 at 02:21
3

I agree with Orbittman when he mentions the overhead involved in the application architecture. It doesn't make for a very good benchmark premise since you can't be sure if the degradation can indeed be solely attributed to the async vs non-async calls.

I've created a really simple benchmark to get a rough comparison between an async and a synchronous call and async loses every time in the overall timing actually, though the data gathering section always seems to end up the same. Have a look: https://gist.github.com/mattGuima/25cb7893616d6baaf970

Having said that, the same thought regarding the architecture applies. Frameworks handle async calls differently: Async and await - difference between console, Windows Forms and ASP.NET

The main thing to remember is to never confuse async with performance gain, because it is completely unrelated and most often it will result on no gain at all, specially with CPU-bound code. Look at the Parallel library for that instead.

Community
  • 1
  • 1
2

Async await is not the silver bullet that some people think it is and in your example is not required. If you were processing the result of the awaitable operation after you received it then you would be able to return a task and continue on the calling thread. You wouldn't have to then wait for the rest of the operation to complete. You would be correct to remove the async/await in the above code.

It's not really possible to answer the question without seeing the calling code either as it depends on what the context is trying to trying to do with the response. What you are getting back is not just a Task but a task in the context of the method that will continue when complete. See http://codeblog.jonskeet.uk/category/eduasync/ for much better information regarding the inner workings of async/await.

Lastly I would question your timings as with an Ajax request to a database and back there other areas with potentially greater latency, such as the HTTP request and response and the DB connection itself. I assume that you're using an ORM and that alone can cause an overhead. I wonder whether it's the async/await that is the problem.

Orbittman
  • 306
  • 1
  • 6