c# - C#异步任务比同步慢
问题描述
你知道为什么同步斐波那契方法比 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
解决方案
你知道为什么同步斐波那契方法比 async/await 快,而且比异步任务快吗?
异步不是提高原始速度。正如您所发现的,总体上需要更长的时间。如果你使用得不好,就像你所做的那样,它会使事情变得非常非常慢,而零收益。
这里的根本问题是您不了解异步的用途。异步用于管理延迟。一旦你内化了这个事实,你就会开始正确地使用它。
延迟是您请求计算或副作用与计算或副作用完成之间的时间间隔。
例如,假设您正在计算一些计算量非常大的东西。例如,您正在计算一个非常复杂的图形,即使您将整个内核都用于计算它也需要 30 多毫秒。您不希望用户界面在进行计算时停止,因此您可以将计算放到另一个线程上,将 CPU 专用于该线程,然后等待结果。 等待的意思是“在等待高延迟操作完成时去找更多的工作要做”。
例如,假设您正在做一些计算成本不高但需要等待外部资源的事情。例如,您正在调用数据库,并且需要 30 多毫秒才能返回结果。在这种情况下,您不想启动线程。该线程只是要睡觉等待结果!相反,您想使用数据库访问 API 的异步版本,并等待高延迟结果。
在您的示例中,您一开始就没有高延迟操作,因此等待它是没有意义的。您在那里所做的只是为运行时创建和管理工作队列创建大量工作,这是您付出但没有从中受益的工作。你的工作需要纳秒;仅对需要毫秒或更长时间的作业使用异步。
仅当您有高延迟操作时才使用异步。异步提高了性能,因为它释放了一个线程以在等待高延迟结果出现时继续工作。如果没有高延迟结果,那么异步只会减慢一切。
推荐阅读
- python - ScrapydWeb:docker-compose 中的连接被拒绝
- sed - sed 读取文件,在特定行之前获取一个块
- tensorflow - DKeras 缺少 1 个必需的位置参数:“输入”
- javascript - 向 Firestore 提交表单时发送电子邮件
- boost - 使用Cmake构建CGAL项目时boost库为空
- hadoop - 如何在 hadoop gcs 连接器中启用 http 请求/响应日志?
- firebase - Firebase 云消息传递 主题数量 主题限制?
- pycharm - PyCharm 在分支开关上禁用开关打开的文件
- ios - 如何在 React Native 中打开 iOS 的 wifi 设置
- postgresql - 尽管有权限,但由于权限而无法 pg_dump