Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步等待vs并行vs单线程性能_C#_Asynchronous_Async Await_Task Parallel Library - Fatal编程技术网

C# 异步等待vs并行vs单线程性能

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

最近,我一直在开发一个应用程序,该应用程序应该是多个服务之上的一个薄层,该应用程序主要执行从不同数据格式到统一格式的映射(许多映射)。我们使用我称之为“linqasync”的东西,但我想看看是否可以提高它的性能

我做了一个简单的实验如下

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)。所以我想在这里提出我的问题

  • linq async不是创建很多任务并并发执行它们吗?为什么它们几乎和单线一样??那么使用它们有什么意义呢
  • 对于一个呼叫,并行似乎是最快的,在重载情况下如何?哪一个最快,为什么
  • 我应该用并行重写linq异步吗??对我来说,表现很重要
  • 或者更确切地说,我的实验有什么缺陷吗??我应该做i/O绑定实验吗

  • 非常感谢。

    异步等待的一般好处不是性能,而是响应能力

    它是关于在发生阻塞操作(通常是I/O)时释放当前线程(客户端UI上的UI线程,ASP.NET上的线程池线程)

    因为每次释放线程时都会有一个上下文切换,以及在抓取线程继续执行时,异步代码都会有一点开销,因此执行效率较低

    但由于它促进了资源的更好利用,整个系统可能会因为响应速度更快而感觉性能更好

    如果可以实现真正的并行性,那么系统的性能会更好


    一般来说,关于性能,您应该始终衡量您的特定用例。

    关于您的第二个和第三个问题