简体   繁体   English

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

[英]async await vs parallel vs single thread performance

recently i've been working on an application that is supposed to be a thin layer on top of several services, this application is mainly doing mappings from different data format to a unified format (a lot of mappings). 最近,我一直在研究一个应该是几种服务之上的薄层的应用程序,该应用程序主要是在进行从不同数据格式到统一格式的映射(很多映射)。 we use what i call "linq async" but I would like to see whether I can improve its performance. 我们使用我所谓的“ linq异步”,但我想看看我是否可以提高其性能。

I did a simple experiment like the following 我做了一个简单的实验,如下所示

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

I expect the senario2(linq async) should be more or less the same as senario3(parallel) as senario2 will create a lot of tasks and execute them concurrently. 我希望senario2(linq async)与senario3(parallel)大致相同,因为senario2将创建许多任务并同时执行它们。 However, my simple experiment tells me im wrong. 但是,我的简单实验告诉我,我错了。 Senario2 is more or less the same as senario1. Senario2与senario1大致相同。 this confuses me a lot and I tried reading many related questions in stackoverflow but cannot find a satisfied answer. 这让我很困惑,我尝试阅读stackoverflow中的许多相关问题,但找不到满意的答案。 Most of the questions are talking about non-blocking UI, whereas my application is a backend service. 大多数问题都在谈论非阻塞UI,而我的应用程序是后端服务。 Also I read about linq async will improve the throughput for a backend service under load, but from my experiment im not convinced. 我还阅读了有关linq async的信息,该文件将提高负载下的后端服务的吞吐量,但是根据我的实验,我不敢相信。 If it's not superior in performance for a single run, how can it improve the throughput under load??? 如果一次运行的性能不佳,如何提高负载下的吞吐量??? Also i noticed the more item in the input array, the better performance i can get from parallel executing(scenario3). 我也注意到输入数组中的项目越多,可以从并行执行(场景3)获得更好的性能。 So I would like to ask my question here. 所以我想在这里问我的问题。

  1. is linq async not create a lot of tasks and execute them concurrently? LINQ异步不创建很多任务并同时执行它们吗? why are they almost same as single thread?? 为什么它们几乎与单线程相同? Then what's the point of using them?? 那么使用它们有什么意义呢?
  2. for one call, parallel seems the fastest, how about under heavy load? 一个电话,并行似乎是最快的,在重负载下又如何呢? which one is fastest and why?? 哪一个最快?为什么?
  3. shall i rewrite linq async with parallel?? 我应该用并行重写linq异步吗? performance is important in my case 对我而言,性能很重要
  4. or rather is there any flaws in my experiment?? 还是我的实验中有任何缺陷? should i do a I/O bound experiment? 我应该进行I / O绑定实验吗?

Many thanks in advance. 提前谢谢了。

The general benefit of async-await is not performance but responsiveness. async-await的一般好处不是性能而是响应能力。

It's about releasing the current thread (the UI thread on client UIs, the thread pool thread on ASP.NET) when a blocking operation (usually, I/O) occurs. 它是在发生阻塞操作(通常是I / O)时释放当前线程(客户端UI上的UI线程,ASP.NET上的线程池线程)。

Because every time the thread is released there's a context switch as well as when a thread is grabbed to continue the execution, asynchronous code has a bit of overhead and, thus, is less performing. 因为每次线程被释放时,都会有一个上下文切换,以及当一个线程被抓住以继续执行时,异步代码会产生一些开销,从而降低性能。

But because it promotes a better use of resources, the overall system might feel more performant just because it's more responsive. 但是,由于它促进了对资源的更好利用,因此整个系统可能会因为响应速度更快而感觉更出色。

When true parallelism is possible than, yes, the system is more performing. 如果可以实现真正的并行性,则系统的性能更高。

In general, regarding performance, you should always measure your particular use case. 通常,关于性能,您应该始终衡量您的特定用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM