C#异步与任务比同步慢

问题描述 投票:1回答:2

你知道为什么同步fibonacci方法比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
c# .net async-await
2个回答
15
投票

你知道为什么同步fibonacci方法比async / await快,并且比异步任务更快?

异步不是为了提高原始速度。正如您所发现的那样,整体需要更长时间。如果你使用它很糟糕,就像你所做的那样,它会使事情变得更加缓慢,对于零利益而言要慢得多。

这里的根本问题是你不明白什么是异步。异步用于管理延迟。一旦你内化了这个事实,你就会开始正确使用它。

延迟是您请求计算或副作用以及计算或副作用完成之间的时间间隔。

例如,假设您正在计算计算成本极高的东西。例如,您正在计算一个非常复杂的图形,即使您将整个核心专用于它,计算也需要30毫秒以上的时间。在进行计算时,您不希望您的用户界面停止,因此您可以将计算放到另一个线程上,将CPU专用于该线程,然后等待结果。等待意味着“在等待高延迟操作完成时,找到更多工作要做”。

例如,假设您正在做一些计算成本不高但需要等待外部资源的事情。例如,您正在调用数据库,并且返回结果需要超过30毫秒。在这种情况下,您不想启动线程。那个线程正在等待结果睡觉!相反,您希望使用数据库访问API的异步版本,并等待高延迟结果。

在您的示例中,您没有开始的高延迟操作,因此等待它是没有意义的。你在那里所做的就是为运行时创建大量工作来创建和管理工作队列,这是你付出的工作但却没有从中受益。你的工作需要几纳秒;仅对占用毫秒或更长时间的作业使用异步。

只有在具有高延迟操作时才使用异步。 Async提高了性能,因为它可以释放一个线程,以便在等待高延迟结果出现时继续工作。如果没有高延迟的结果,那么异步只会减慢一切。


1
投票

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

当你在内存中做的事情,比如计算fibonacci,做同步,在内存计算中创建一个单独的线程/上下文的开销太大了

除非你有一个等待计算结束的ui线程,你可以实现异步,但要注意你确实会有一些性能损失......

© www.soinside.com 2019 - 2024. All rights reserved.