C#与任务异步比同步慢

时间:2018-09-18 19:01:30

标签: c# .net async-await

您知道为什么同步斐波那契方法比异步/等待更快,而又比异步任务快吗?

我在每种项目方法上都使用了异步,所以主要是这种方法太糟糕了...

代码:

        static int FibonacciSync(int number)
        {
            if (number == 0) { return 0; }
            else if (number == 1) { return 1; }
            else
            {
                var t1 = FibonacciSync(number - 1);
                var t2 = FibonacciSync(number - 2);
                return t1 + t2;
            }
        }

        async static Task<int> FibonacciAwait(int number)
        {
            if (number == 0) 
            { return 0; }
            else if (number == 1) 
            { return 1; }
            else
            {
                var task1 = FibonacciAwait(number - 1);
                var task2 = FibonacciAwait(number - 2);
                return (await task1) + (await task2);
            }
        }

        static Task<int> FibonacciAsync(int number)
        {
            if (number == 0) 
            { return Task.FromResult(0); }
            else if (number == 1) 
            { return Task.FromResult(1); }
            else
            {
                return FibonacciAsync(number - 1).ContinueWith(task1 =>
                {
                    return FibonacciAsync(number - 2).ContinueWith(task2 =>
                    {
                        return task1.Result + task2.Result;
                    });
                }).Unwrap();
            }
        }

结果:

  • 同步:00:00:00.0121900
  • 等待:00:00:00.2118170
  • 异步:00:00:02.6211660

2 个答案:

答案 0 :(得分:14)

Do you know why sync fibonacci method is faster than async/await and that is faster than async task?

Asynchrony is not about improving raw speed. As you've discovered, it takes longer overall. If you use it poorly, as you have done, it makes things much, much slower for zero benefit.

The fundamental problem here is that you don't understand what asynchrony is for. Asynchrony is for managing latency. Once you internalize that fact, you'll start using it correctly.

Latency is the gap in time between when you request a computation or side effect, and when the computation or side effect is complete.

For example, suppose you are computing something that is extremely computationally expensive. You're computing a really complicated graphic, for example, and it is going to take more than 30 milliseconds to compute even if you dedicate an entire core to it. You do not want your user interface to stall while you're doing the computation, so you can put the computation onto another thread, dedicate a CPU to that thread, and await the result. An await means "go find more work to do while I am waiting for a high latency operation to complete".

For example, suppose you are doing something that is not computationally expensive but requires waiting on an external resource. You're calling into a database, for example, and it is going to take more than 30 ms to get the result back. In this case you do not want to spin up a thread. That thread is just going to sleep waiting for the result! Instead you want to use the async version of the database access API, and await the high latency result.

In your example you don't have a high-latency operation to begin with, so it makes no sense to await it. All you're doing there is creating a lot of work for the runtime to create and manage the work queues, and that is work you are paying for but getting no benefit from. Your work takes nanoseconds; only use asynchrony for jobs that take milliseconds or longer.

Only use async when you have a high-latency operation. Async improves performance because it frees up a thread to keep on doing work while it is waiting for a high-latency result to appear. If there is no high-latency result then async will just slow everything down.

答案 1 :(得分:0)

一个好的经验法则:仅对使用外部资源的函数使用异步调用:文件系统,数据库,http调用,...

当您在内存中做事时,例如计算斐波那契,使其同步时,为内存计算创建单独的线程/上下文的开销太大了

除非您有一个ui线程正在等待计算完成,否则您可以异步实现它,但是请注意,您的确会损失一些性能...