According to ASP.NET Core Performance Best Practices from ASP.NET team:
Avoid blocking calls
ASP.NET Core apps should be designed to process many requests simultaneously. Asynchronous APIs allow a small pool of threads to handle thousands of concurrent requests by not waiting on blocking calls. Rather than waiting on a long-running synchronous task to complete, the thread can work on another request.
A common performance problem in ASP.NET Core apps is blocking calls that could be asynchronous. Many synchronous blocking calls lead to Thread Pool starvation and degraded response times.
- Do make hot code paths asynchronous.
- Do call data access, I/O, and long-running operations APIs asynchronously if an asynchronous API is available.
- Do not use Task.Run() to make a synchronous API asynchronous.
- Do make controller/Razor Page actions asynchronous. The entire call stack is asynchronous in order to benefit from async/await patterns.
Avoid synchronous read or write on HttpRequest/HttpResponse body
All I/O in ASP.NET Core is asynchronous. Servers implement the Stream interface, which has both synchronous and asynchronous overloads. The asynchronous ones should be preferred to avoid blocking thread pool threads. Blocking threads can lead to thread pool starvation.
Prefer ReadFormAsync over Request.Form
Use HttpContext.Request.ReadFormAsync
instead of HttpContext.Request.Form
. HttpContext.Request.Form
can be safely read-only with the following conditions:
- The form has been read by a call to
ReadFormAsync
, and
- The cached form value is being read using
HttpContext.Request.Form
Optimize data access and I/O
Interactions with a data store and other remote services are often the slowest parts of an ASP.NET Core app. Reading and writing data efficiently is critical for good performance.
- Do call all data access APIs asynchronously.