C# 异步等待vs并行vs单线程性能
最近,我一直在开发一个应用程序,该应用程序应该是多个服务之上的一个薄层,该应用程序主要执行从不同数据格式到统一格式的映射(许多映射)。我们使用我称之为“linqasync”的东西,但我想看看是否可以提高它的性能 我做了一个简单的实验如下C# 异步等待vs并行vs单线程性能,c#,asynchronous,async-await,task-parallel-library,C#,Asynchronous,Async Await,Task Parallel Library,最近,我一直在开发一个应用程序,该应用程序应该是多个服务之上的一个薄层,该应用程序主要执行从不同数据格式到统一格式的映射(许多映射)。我们使用我称之为“linqasync”的东西,但我想看看是否可以提高它的性能 我做了一个简单的实验如下 using System; using System.Collections.Async; using System.Collections.Concurrent; using System.Collections.Generic; using System.D
using System;
using System.Collections.Async;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
int max = 100;
int[] input = Enumerable.Range(1, max).ToArray();
Work w = new Work();
// senario 1
sw.Restart();
var result1 = input.Select(x => w.LongHoursWork(x)).ToArray();
sw.Stop();
Console.WriteLine($"One Thread: {sw.ElapsedMilliseconds}");
// senario 2
sw.Restart();
var result2 = MainAsync(input, w).GetAwaiter().GetResult();
sw.Stop();
Console.WriteLine($"Linq async: {sw.ElapsedMilliseconds}");
// senario 3
sw.Restart();
var result3 = input.AsParallel().Select(x => w.LongHoursWork(x)).ToArray();
sw.Stop();
Console.WriteLine($"Parallel: {sw.ElapsedMilliseconds}");
// check result
for (int i = 0; i < max; i++)
{
if(result1[i] == result2[i] && result2[i] == result3[i])// && result4.Contains(result1[i]))
continue;
throw new ArgumentNullException();
}
Console.ReadKey();
}
static async Task<string[]> MainAsync(int[] input, Work work)
{
var result = await Task.WhenAll(input.Select(async x => await work.LongHoursWorkAsync(x)));
return result;
}
}
public class Work
{
public string LongHoursWork(int i)
{
for (int ix = 0; ix < 100000; ix++)
{
i += ix;
}
return i.ToString();
}
public async Task<string> LongHoursWorkAsync(int i)
{
return await Task.FromResult(LongHoursWork(i));
}
}
}
//execution result:
//One Thread: 88
//Linq async: 97
//Parallel: 59
// if i change the input array to 600(similar to what i have in production
// environment)
// execution result:
// One Thread: 347
// Linq async: 292
// Parallel: 101
使用系统;
使用System.Collections.Async;
使用System.Collections.Concurrent;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用System.Net.Http;
使用系统线程;
使用System.Threading.Tasks;
名称空间控制台EAPP1
{
班级计划
{
静态void Main(字符串[]参数)
{
int max=100;
int[]input=Enumerable.Range(1,max.ToArray();
工作w=新工作();
//塞纳里奥1号
sw.Restart();
var result1=input.Select(x=>w.LongHoursWork(x)).ToArray();
sw.Stop();
WriteLine($“一个线程:{sw.elapsedmillesons}”);
//塞纳里奥2号
sw.Restart();
var result2=mainsync(输入,w).GetAwaiter().GetResult();
sw.Stop();
WriteLine($“Linq异步:{sw.elapsedmillesons}”);
//塞纳里奥3号
sw.Restart();
var result3=input.AsParallel().Select(x=>w.LongHoursWork(x)).ToArray();
sw.Stop();
WriteLine($“Parallel:{sw.elapsedmillesons}”);
//检查结果
对于(int i=0;iawait work.LongHoursWorkAsync(x));
返回结果;
}
}
公开课
{
公共字符串长时工作(int i)
{
对于(int-ix=0;ix<100000;ix++)
{
i+=ix;
}
返回i.ToString();
}
公共异步任务LongHoursWorkAsync(int i)
{
返回等待任务。来自结果(长时间工作(i));
}
}
}
//执行结果:
//一线:88
//Linq异步:97
//并行:59
//如果我将输入数组更改为600(与生产中的类似
//(环境)
//执行结果:
//一线:347
//Linq异步:292
//平行线:101
我希望senario2(linq异步)应该与senario3(并行)大致相同,因为senario2将创建许多任务并并发执行它们。然而,我的简单实验告诉我我错了。Senario2与senario1大致相同。这让我很困惑,我试着阅读
stackoverflow中有许多相关问题,但无法找到满意的答案。大多数问题都是关于非阻塞UI的,而我的应用程序是一个后端服务。此外,我还了解到LINQAsync将在负载下提高后端服务的吞吐量,但从我的实验来看,我并不确信这一点。如果单次运行的性能并不优越,那么如何提高负载下的吞吐量???我还注意到,输入数组中的项目越多,并行执行的性能就越好(场景3)。所以我想在这里提出我的问题
非常感谢。异步等待的一般好处不是性能,而是响应能力 它是关于在发生阻塞操作(通常是I/O)时释放当前线程(客户端UI上的UI线程,ASP.NET上的线程池线程) 因为每次释放线程时都会有一个上下文切换,以及在抓取线程继续执行时,异步代码都会有一点开销,因此执行效率较低 但由于它促进了资源的更好利用,整个系统可能会因为响应速度更快而感觉性能更好 如果可以实现真正的并行性,那么系统的性能会更好
一般来说,关于性能,您应该始终衡量您的特定用例。关于您的第二个和第三个问题