How does the ubiquitous Async/Await in .Net Core improve performance?

1. Introduction

Async/Await is really ubiquitous in .Net Core, and there are asynchronous operations everywhere, so why use it? what's the effect? Others say it can improve performance? After reading a bunch of articles on the Internet, I got dizzy and didn't make it clear.

So here we will solve these questions one by one from theory, practice and principle.

2. What is the use of Async/Await?

1. Example of Async/Await usage

The usage is very simple, so I won’t go into details about how to use it here, but just provide an example, and our goal is to study its function.

 public class AsyncAwaitTest
    {
        public void Start()
        {
            Console.WriteLine($"aaa,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            AsyncMethod();
            Console.WriteLine($"eee,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            Console.ReadLine();
        }
        public async Task<bool> AsyncMethod()
        {
            Console.WriteLine($"bbb,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            await Task.Run(() => {

                Thread.Sleep(500);
                Console.WriteLine($"ccc,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            });
            Console.WriteLine($"ddd,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            return true;
        }
    }

2. The characteristics of async/await

1) Will not block the thread

From the execution sequence of the example, it can be seen that when the async/await method is executed, the main thread encounters the await keyword, the main thread returns to execute "eee", and then releases, instead of waiting, a new sub-thread is opened to execute 6 For other businesses, the method before await is still executed by the main thread, and the method after await will continue to execute after thread 6 finishes executing.

2) Write asynchronously in a synchronous manner

Although asynchronous is used, it still waits for the execution result before proceeding. The execution process is synchronous.

3. Can async/await improve performance?

This should be everyone's biggest concern.

Can the performance of a single request be improved?

The answer is no. It is obvious to see that await waits for the result and then executes the subsequent logic. It is still serial, how many seconds should be executed, and the thread is switched to process in the middle. Compared with synchronization, there is more loss of switching threads. .

So what's the point of async/await?

When multiple requests are processed concurrently and resources are limited, it can increase throughput (requests processed per unit time) and increase cpu utilization.

Simply put, there are 10 threads, and the speed of each thread has not been improved, and then the QPS can be improved? !

Let’s take a look at a description from Microsoft’s official website

  This model handles typical server scenario workloads well. Since there are no threads dedicated to blocking outstanding tasks, the server thread pool can serve more web requests.

  Consider using two servers: one running asynchronous code and one not running asynchronous code. For this example, only 5 threads per server are available for server requests. This word count is too small to be practical and is for demonstration purposes only.

  Let's say both servers receive 6 concurrent requests. Each request performs an I/O operation. A server not running asynchronous code has to queue a 6th request until one of the 5 threads has finished the I/O intensive work

and wrote the response. At this point the 20th request is received and the server may start to slow down due to the long queue.

  Servers running with asynchronous code also need to queue the 6th request, but because of the use of async and await, every thread will be released when the I/O intensive work starts, without waiting for the work to finish.

By the time the 20th request is received, the queue of incoming requests will be small (if there are any more), and the server will not be slow.

  Although this is a contrived example, it works similarly in the real world. In fact, using async and await enables the server to dedicate a thread to each request it receives.

The server handles an order of magnitude of requests.

  Pay attention to the I/O intensive described on the official website above. What is I/O intensive? , that is, the CPU performance is much better than the hard disk memory, most of the time the CPU is waiting for IO read and write operations. For example, when reading a file, the CPU does not need to participate in reading the file. You only need to send a command to the hard disk. After the hard disk reads the file, it will notify the CPU to continue processing. This is called DMA technology .

  DMA (Direct Memory Access) is an important feature of all modern computers. It refers to a high-speed data transfer operation that allows data to be read and written directly between external devices and memory, neither through the CPU nor the need for cpu intervention.

  At this time, asynchrony shows its advantages. For example, it takes 1s to read a file. If it is a synchronous operation, then there is a thread waiting for 1s before executing it. If it is asynchronous, when the file is read, the thread is released. After the file is read, the hard disk notifies the CPU to send another thread to continue processing. In the middle 1 second, the original thread can process other requests.

4. Code comparison instructions

The process of synchronous request is

 It can be seen that when the hard disk is reading the file, the thread is waiting. At this time, thread 1 does not work during this 1s, and is in an idle state.

The process of asynchronous request is

 When an asynchronous request is made, thread 1 encounters the await keyword, returns after issuing a command, and then releases it. After the hard disk reads the data, it will notify the CPU. At this time, the CPU sends a new thread to continue processing.

Therefore, during the 1 second of reading the file, thread 1 can process other requests, and there is no time to wait. This increases the utilization rate of the cpu, and the number of requests processed per unit time increases.

CPU-intensive asynchrony cannot improve QPS. The following code is CPU-intensive.

CPU-intensive: Computation-intensive, hard disk, memory performance is much better than CPU, or less need to access I/O devices.

public class HomeController : Controller
    {
        /// <summary>
        /// 同步请求
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public string GetData()
        {
            var result = System.IO.File.ReadAllBytes(@"F:\package\package.rar");
            return "ok";
        }

        /// <summary>
        /// 异步请求
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task<string> GetDataAsync2()
        {
            var result = await System.IO.File.ReadAllBytesAsync(@"F:\package\package.rar");
            return "ok";
        }
    }
     /// <summary>
        /// 异步请求
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task<string> GetDataAsync2()
        {
            await Task.Run(() => {
                Thread.Sleep(100);//模拟业务处理耗时
            });
            return "ok";
        }

Here, the main thread encounters await, although it is released, but there is another thread in the await to continue working, and the cpu (thread) is not idle.

What are the IO operations in I/O intensive?

File read and write, http request, database request, redis request. . . etc.

 Which ones are recommended for asynchrony in development?

Web development recommendation, with Async API, Action, Filter, database access, middleware, etc. . .


Reposted from: https://www.cnblogs.com/wei325/p/15957951.html

Guess you like

Origin blog.csdn.net/u014683833/article/details/123430370