It’s been a long time since I’ve written a blog. The product company I’m working on this year just held a press conference these two days. After a little leisure time, I thought about whether there is room for performance optimization of the products we make, so I thought of .Net’s asynchronous function to optimize performance. , but by what proportion can it be increased? It happens that a friend is doing asynchronous performance testing in various languages (for questions about asynchronous and synchronization, please refer to the guest "AIO and BIO Interface Performance Comparison"), so I wrote a C# test program today.
First, build an ASP.NET MVC WebAPI project. In the default controller values, add two methods:
// GET api/values?sleepTime=10 [HttpGet] public async Task<string> ExecuteAIO(int sleepTime) { await Task.Delay(sleepTime); return "Hello world,"+ sleepTime; } [HttpGet] // GET api/values?sleepTime2=10 public string ExecuteBIO(int sleepTime2) { System.Threading.Thread.Sleep(sleepTime2); return "Hello world," + sleepTime2; }
Then, create a Console program to test this web API:
class Program { static void Main(string[] args) { Console.WriteLine("按任意键开始测试 WebAPI:http://localhost:62219/api/values?sleepTime={int}"); Console.Write("请输入线程数:"); int threadNum = 100; int.TryParse(Console.ReadLine(), out threadNum); while (Test(threadNum)) ; Console.ReadLine(); Console.ReadLine(); } private static bool Test(int TaskNumber) { Console.Write("请输入此API方法的睡眠时间(毫秒),输入非数字内容退出:"); string input = Console.ReadLine(); int SleepTime = 50; if (!int.TryParse(input, out SleepTime)) return false; HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:62219/"); var result = client.GetStringAsync("api/values?sleepTime=" + input).Result; Console.WriteLine("Result:{0}", result); //int TaskNumber = 1000; Console.WriteLine("{0}次 BIO(同步)测试(睡眠{1} 毫秒):", TaskNumber, SleepTime); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); Task[] taskArr = new Task[TaskNumber]; for (int i = 0; i < TaskNumber; i++) { Task task = client.GetStringAsync("api/values?sleepTime2=" + SleepTime); taskArr[i] = task; } Task.WaitAll(taskArr); sw.Stop(); double useTime1 = sw.Elapsed.TotalSeconds; Console.WriteLine("耗时(秒):{0},QPS:{1,10:f2}", useTime1, TaskNumber/useTime1); sw.Reset(); Console.WriteLine("{0}次 AIO(异步)测试(睡眠{1} 毫秒):", TaskNumber, SleepTime); sw.Start(); for (int i = 0; i < TaskNumber; i++) { Task task = client.GetStringAsync("api/values?sleepTime=" + SleepTime); taskArr[i] = task; } Task.WaitAll(taskArr); sw.Stop(); double useTime2 = sw.Elapsed.TotalSeconds; Console.WriteLine("耗时(秒):{0},QPS:{1,10:f2}", useTime2, TaskNumber / useTime2); return true; } }
View Code
In fact, it is mainly the following lines of code:
HttpClient client = new HttpClient(); client.BaseAddress = new 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 this test and the results are as follows:
按任意键开始测试 WebAPI:http://localhost:62219/api/values?sleepTime={int} 请输入线程数:1000 请输入此API方法的睡眠时间(毫秒),输入非数字内容退出:10 Result:"Hello world,10" 1000次 BIO(同步)测试(睡眠10 毫秒): 耗时(秒):1.2860545,QPS: 777.57 1000次 AIO(异步)测试(睡眠10 毫秒): 耗时(秒):0.4895946,QPS: 2042.51 请输入此API方法的睡眠时间(毫秒),输入非数字内容退出:100 Result:"Hello world,100" 1000次 BIO(同步)测试(睡眠100 毫秒): 耗时(秒):8.2769307,QPS: 120.82 1000次 AIO(异步)测试(睡眠100 毫秒): 耗时(秒):0.5435111,QPS: 1839.89
I originally wanted to try to test 10,000 threads, but an error was reported.
The above test results show that the QPS is not high, but because IISExpress is used and the performance of different web server software is different, it is necessary to compare the in-process QPS results, so create a new A console program with the following code:
##
class Program { static void Main(string[] args) { Console.WriteLine("按任意键开始测试 "); Console.Write("请输入线程数:"); int threadNum = 100; int.TryParse(Console.ReadLine(), out threadNum); while (Test(threadNum)) ; Console.ReadLine(); Console.ReadLine(); } private static bool Test(int TaskNumber) { Console.Write("请输入此API方法的睡眠时间(毫秒),输入非数字内容退出:"); string input = Console.ReadLine(); int SleepTime = 50; if (!int.TryParse(input, out SleepTime)) return false; var result = ExecuteAIO(SleepTime).Result; Console.WriteLine("Result:{0}", result); //int TaskNumber = 1000; Console.WriteLine("{0}次 BIO(同步)测试(睡眠{1} 毫秒):", TaskNumber, SleepTime); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); Task[] taskArr = new Task[TaskNumber]; for (int i = 0; i < TaskNumber; i++) { Task task = Task.Run<string>(()=> ExecuteBIO(SleepTime)); taskArr[i] = task; } Task.WaitAll(taskArr); sw.Stop(); double useTime1 = sw.Elapsed.TotalSeconds; Console.WriteLine("耗时(秒):{0},QPS:{1,10:f2}", useTime1, TaskNumber / useTime1); sw.Reset(); Console.WriteLine("{0}次 AIO(异步)测试(睡眠{1} 毫秒):", TaskNumber, SleepTime); sw.Start(); for (int i = 0; i < TaskNumber; i++) { Task task = ExecuteAIO(SleepTime); taskArr[i] = task; } Task.WaitAll(taskArr); sw.Stop(); double useTime2 = sw.Elapsed.TotalSeconds; Console.WriteLine("耗时(秒):{0},QPS:{1,10:f2}", useTime2, TaskNumber / useTime2); return true; } public static async Task<string> ExecuteAIO(int sleepTime) { await Task.Delay(sleepTime); return "Hello world," + sleepTime; } public static string ExecuteBIO(int sleepTime2) { System.Threading.Thread.Sleep(sleepTime2); //不能在非异步方法里面使用 Task.Delay,否则可能死锁 //Task.Delay(sleepTime2).Wait(); return "Hello world," + sleepTime2; } }
View Code
Note that the key code only has the following two methods:public static async Task<string> ExecuteAIO(int sleepTime) { await Task.Delay(sleepTime); return "Hello world," + sleepTime; } public static string ExecuteBIO(int sleepTime2) { System.Threading.Thread.Sleep(sleepTime2); //不能在非异步方法里面使用 Task.Delay,否则可能死锁 //Task.Delay(sleepTime2).Wait(); return "Hello world," + sleepTime2; }
Task[] taskArr = new Task[TaskNumber]; for (int i = 0; i < TaskNumber; i++) { Task task = Task.Run<string>(()=> ExecuteBIO(SleepTime)); taskArr[i] = task; } Task.WaitAll(taskArr);
##
for (int i = 0; i < TaskNumber; i++) { Task task = ExecuteAIO(SleepTime); taskArr[i] = task; } Task.WaitAll(taskArr);
The following are the results of non-Web in-process asynchronous multi-threading and synchronous multi-threading:
请输入线程数:1000 请输入此API方法的睡眠时间(毫秒),输入非数字内容退出:10 Result:Hello world,10 1000次 BIO(同步)测试(睡眠10 毫秒): 耗时(秒):1.3031966,QPS: 767.34 1000次 AIO(异步)测试(睡眠10 毫秒): 耗时(秒):0.026441,QPS: 37820.05 请输入此API方法的睡眠时间(毫秒),输入非数字内容退出:100 Result:Hello world,100 1000次 BIO(同步)测试(睡眠100 毫秒): 耗时(秒):9.8502858,QPS: 101.52 1000次 AIO(异步)测试(睡眠100 毫秒): 耗时(秒):0.1149469,QPS: 8699.67 请输入线程数:10000 请输入此API方法的睡眠时间(毫秒),输入非数字内容退出:10 Result:Hello world,10 10000次 BIO(同步)测试(睡眠10 毫秒): 耗时(秒):7.7966125,QPS: 1282.61 10000次 AIO(异步)测试(睡眠10 毫秒): 耗时(秒):0.083922,QPS: 119158.27 请输入此API方法的睡眠时间(毫秒),输入非数字内容退出:100 Result:Hello world,100 10000次 BIO(同步)测试(睡眠100 毫秒): 耗时(秒):34.3646036,QPS: 291.00 10000次 AIO(异步)测试(睡眠100 毫秒): 耗时(秒):0.1721833,QPS: 58077.64
Note: The test environment for the above test results is
Intel i7-4790K CPU, 4 cores and 8 threads, 16GB of memory, Win10 Enterprise Edition
The above is the detailed content of Sample code for asynchronous performance testing in .net. For more information, please follow other related articles on the PHP Chinese website!