Task.WaitAll()之间的性能差距问题并按顺序执行Task.Wait

时间:2012-04-22 05:19:44

标签: c# multithreading asynchronous concurrency task

我想为某些同步代码添加并发性,并在流程中发现性能问题,这很难理解。

以下代码的运行结果是:

Mission Fibonacci1Async cost 9.4195388 seconds, value 75025
Mission Fibonacci2Async cost 0.2260129 seconds, value 75025

唯一不同的是第2个函数添加了一行 await Task.WhenAll(new Task [] {t1,t2}); ,使性能提高40倍。

有人可以向我解释一下吗?

    static Task<int> Fibonacci1Async(int n)
    {
        return Task.Run<int>(() => Fibonacci1(n));
    }

    static int Fibonacci1(int n)
    {
        if (n == 0) return 0;
        else if (n == 1) return 1;
        else
        {
            var t1 = Fibonacci1Async(n - 1);
            var t2 = Fibonacci1Async(n - 2);
            return t1.Result + t2.Result;
        }
    }

    static Task<int> Fibonacci2Async(int n)
    {
        return Task.Run<int>(() => Fibonacci2(n));
    }

    static int Fibonacci2(int n)
    {
        if (n == 0) return 0;
        else if (n == 1) return 1;
        else
        {
            var t1 = Fibonacci2Async(n - 1);
            var t2 = Fibonacci2Async(n - 2);

            Task.WaitAll(new Task[] { t1, t2 });
            return t1.Result + t2.Result;
        }
    }

    static void Benchmark(Func<int, Task<int>> func)
    {
        DateTime time = DateTime.Now;
        var task = func(25);
        task.Wait();
        TimeSpan cost = DateTime.Now - time;
        Console.WriteLine("Mission {0} cost {1} seconds value {2}", func.Method.Name, cost.TotalSeconds, task.Result);
    }

    static void Main(string[] args)
    {
        Benchmark(Fibonacci1Async);
        Benchmark(Fibonacci2Async);
        Console.ReadKey();
        return;
    }

1 个答案:

答案 0 :(得分:1)

我怀疑答案与Task.Wait inlining有关。

在表达式t1.Result + t2.Result中,+运算符从左到右计算其参数(连续)。因此它会阻止t1,然后阻止t2

我在你的系统上猜测,t1已经开始但不是t2。在这种情况下,Task.WaitAll可以将t2“内联”到当前线程池任务中,而不是启动新任务,但+将阻止t1

这只是猜测;您应该使用分析器来确切了解发生了什么。

我无法在我的系统上重现这一点。我总是看到两个版本大致相同,即使处理器关联应用于流程也是如此。

P.S。命名约定Async在这里并不适用。此代码未使用async / await - 它正在使用任务并行库。