Haven't written a blog for a long time, this year to do the product companies have just opened a conference, a little idle down, think we do the product has no performance optimization space, then thought of. NET is asynchronous to optimize performance, but how much can it improve? Just have a friend doing asynchronous performance testing in various languages (for asynchronous and synchronous issues, refer to the customer "AIO vs. Bio interface Performance Comparison"), so I wrote a test program for C # today.
First, build an ASP. NET MVC Webapi project, adding two methods to the default controller values:
//GET api/values?sleeptime=10[HttpGet] Public Asynctask<string> Executeaio (intsleeptime) { awaitTask.delay (sleeptime); return "Hello World,"+Sleeptime; } [HttpGet]//GET api/values?sleeptime2=10 Public stringExecutebio (intsleepTime2) {System.Threading.Thread.Sleep (sleepTime2); return "Hello World,"+sleepTime2; }
Then, set up a console program to test the Web API:
classProgram {Static voidMain (string[] args) {Console.WriteLine ("Press any key to start the test webapi:http://localhost:62219/api/values?sleeptime={int}"); Console.Write ("Please enter the number of threads:"); intThreadnum = -; int. TryParse (Console.ReadLine (), outthreadnum); while(Test (threadnum)); Console.ReadLine (); Console.ReadLine (); } Private Static BOOLTest (intTasknumber) {Console.Write ("Please enter the sleep time (in milliseconds) of this API method and enter non-digital content to exit:"); stringinput =Console.ReadLine (); intSleeptime = -; if(!int. TryParse (Input, outsleeptime)) return false; HttpClient Client=NewHttpClient (); Client. BaseAddress=NewUri ("http://localhost:62219/"); varresult = client. Getstringasync ("api/values?sleeptime="+input). Result; Console.WriteLine ("result:{0}", result); //int tasknumber = +;Console.WriteLine ("{0} times BIO (sync) test (sleep {1} milliseconds):", Tasknumber, sleeptime); System.Diagnostics.Stopwatch SW=NewSystem.Diagnostics.Stopwatch (); Sw. Start (); Task[] Taskarr=NewTask[tasknumber]; for(inti =0; i < Tasknumber; i++) {Task Task= client. Getstringasync ("api/values?sleeptime2="+sleeptime); Taskarr[i]=task; } task.waitall (Taskarr); Sw. Stop (); DoubleUseTime1 =SW. Elapsed.totalseconds; Console.WriteLine ("time Elapsed (seconds): {0},QPS:{1,10:F2}", UseTime1, tasknumber/useTime1); Sw. Reset (); Console.WriteLine ("{0} times AIO (asynchronous) test (sleep {1} milliseconds):", Tasknumber, sleeptime); Sw. Start (); for(inti =0; i < Tasknumber; i++) {Task Task= client. Getstringasync ("api/values?sleeptime="+sleeptime); Taskarr[i]=task; } task.waitall (Taskarr); Sw. Stop (); DoubleUseTime2 =SW. Elapsed.totalseconds; Console.WriteLine ("time Elapsed (seconds): {0},QPS:{1,10:F2}", UseTime2, Tasknumber/useTime2); return true; } }View Code
In fact, the following lines of code are mainly:
Newnew Uri ("http://localhost:62219/"); var result = client. Getstringasync ("api/values?sleeptime=" + input). Result;
Note that you may need to use NuGet to add the following package:
Microsoft.AspNet.WebApi.Client
Finally, run the test with the following results:
Press any key to start the test webapi:http://localhost:62219/api/values?sleeptime={int} Please enter the number of threads: 1000 Enter the sleep time (in milliseconds) for this API method, Enter non-digital content exit: 10Result: "Hello world,10" 1000 Times BIO (sync) test (sleep 10 milliseconds): time-consuming (seconds): 1.2860545,qps: 777.571 AIO (asynchronous) test (sleep 10 milliseconds) : Time-consuming (seconds): 0.4895946,qps: 2042.51 Enter the sleep time (in milliseconds) of this API method, enter non-digital content exit: 100Result: "Hello world,100" 1000 Times BIO (sync) test (sleep 100 ms ): Time-consuming (seconds): 8.2769307,qps: 120.821 AIO (asynchronous) test (sleep 100 milliseconds): time-consuming (seconds): 0.5435111,qps: 1839.89
Originally wanted to try to test 10,000 threads, but error.
The above test results, the QPS is not high, but because of the use of iisexpress, different Web server software performance is not the same, so we have to compare the results of the in-process QPS, and then create a new console program, the code is as follows:
classProgram {Static voidMain (string[] args) {Console.WriteLine ("Press any key to start the test"); Console.Write ("Please enter the number of threads:"); intThreadnum = -; int. TryParse (Console.ReadLine (), outthreadnum); while(Test (threadnum)); Console.ReadLine (); Console.ReadLine (); } Private Static BOOLTest (intTasknumber) {Console.Write ("Please enter the sleep time (in milliseconds) of this API method and enter non-digital content to exit:"); stringinput =Console.ReadLine (); intSleeptime = -; if(!int. TryParse (Input, outsleeptime)) return false; varresult =Executeaio (sleeptime). Result; Console.WriteLine ("result:{0}", result); //int tasknumber = +;Console.WriteLine ("{0} times BIO (sync) test (sleep {1} milliseconds):", Tasknumber, sleeptime); System.Diagnostics.Stopwatch SW=NewSystem.Diagnostics.Stopwatch (); Sw. Start (); Task[] Taskarr=NewTask[tasknumber]; for(inti =0; i < Tasknumber; i++) {Task Task= task.run<string> (() =Executebio (sleeptime)); Taskarr[i]=task; } task.waitall (Taskarr); Sw. Stop (); DoubleUseTime1 =SW. Elapsed.totalseconds; Console.WriteLine ("time Elapsed (seconds): {0},QPS:{1,10:F2}", useTime1, Tasknumber/useTime1); Sw. Reset (); Console.WriteLine ("{0} times AIO (asynchronous) test (sleep {1} milliseconds):", Tasknumber, sleeptime); Sw. Start (); for(inti =0; i < Tasknumber; i++) {Task Task=Executeaio (sleeptime); Taskarr[i]=task; } task.waitall (Taskarr); Sw. Stop (); DoubleUseTime2 =SW. Elapsed.totalseconds; Console.WriteLine ("time Elapsed (seconds): {0},QPS:{1,10:F2}", UseTime2, Tasknumber/useTime2); return true; } Public Static Asynctask<string> Executeaio (intsleeptime) { awaitTask.delay (sleeptime); return "Hello World,"+Sleeptime; } Public Static stringExecutebio (intsleepTime2) {System.Threading.Thread.Sleep (sleepTime2); //Task.delay cannot be used inside a non-async method, otherwise it might deadlock//Task.delay (sleepTime2). Wait (); return "Hello World,"+sleepTime2; } }View Code
Note that the key code has only the following two methods:
Public Static Asynctask<string> Executeaio (intsleeptime) { awaitTask.delay (sleeptime); return "Hello World,"+Sleeptime; } Public Static stringExecutebio (intsleepTime2) {System.Threading.Thread.Sleep (sleepTime2); //Task.delay cannot be used inside a non-async method, otherwise it might deadlock//Task.delay (sleepTime2). Wait (); return "Hello World,"+sleepTime2; }
These two methods are the same as the Webapi test method code, but the calling code is slightly different:
Synchronous invocation:
New Task[tasknumber]; for (int0; i < tasknumber; i++) { = task.run<string> (() = Executebio (sleeptime)); = task; } Task.waitall (Taskarr);
Asynchronous invocation:
for (int0; i < tasknumber; i++) { = Executeaio (sleeptime); = task; } Task.waitall (Taskarr);
As can be seen here, when testing, synchronous and asynchronous calls, the client code is used by multi-threading, the main difference is that the asynchronous method uses the Async/await statement.
The following are the results of non-web, in-process asynchronous multithreading and synchronous Multithreading:
Please enter the number of threads: 1000 Enter the sleep time (in milliseconds) of this API method, enter non-digital content exit: 10result:hello world,101000 BIO (sync) test (sleep 10 ms): Time Elapsed (seconds): 1.3031966,qps: 767.341 AIO (asynchronous) test (sleep 10 milliseconds): time-consuming (seconds): 0.026441,qps: 37820.05 Enter the sleep time (in milliseconds) of this API method and enter non-digital content to exit: 100result:hello World , 1.001 million BIO (sync) test (sleep 100 ms): Time-consuming (seconds): 9.8502858,qps: 101.521 AIO (asynchronous) test (sleep 100 milliseconds): time-consuming (seconds): 0.1149469,qps: 8699.67 Enter the number of threads: 10000 Enter the sleep time (in milliseconds) of this API method and enter non-digital content to exit: 10result:hello world,1010000 BIO (sync) test (sleep 10 ms): Time consuming (seconds): 7.7966125, QPS: 1282.611 AIO (asynchronous) test (sleep 10 milliseconds): time-consuming (seconds): 0.083922,qps:119158.27 Enter the sleep time (in milliseconds) of this API method and enter non-digital content to exit: 100Result: Hello world,10010000 times BIO (sync) test (sleep 100 ms): Time-consuming (seconds): 34.3646036,qps: 291.001-time AIO (asynchronous) test (sleep 100 ms) : Time-consuming (seconds): 0.1721833,qps: 58077.64
The results show that. NET program to open 10,000 native threads, the asynchronous method of QPS more than 100,000, and the synchronization method only 1000多 points, the performance gap is still very large.
Summarize:
Whether it is a normal program or a Web program, using asynchronous multithreading can greatly improve the throughput of the system.
. NET asynchronous performance testing (including ASP. Webapi Async method)