感觉async await 异步编程 并不能提升性能啊?

2019-12-06 09:16发布

问题:

我有2个方法 代码相同
都是执行写入文件IO操作 一个同步 一个异步

然后我用POSTMAN 分别用200个线程 去同时测试2个接口

结果很意外 2个接口 同时执行完成的速度 异步更慢

之前经常看别人博主说 尽量用异步来优化自己的代码

但是经过自己测试后 发现使用异步的效率结果更差,后面仔细想了下 好像确实是这么回事

所谓的异步操作就是一个A线程在执行任务的时候,执行到一半 再把任务交给B另一个线程,

然后A线程就开始等待B的执行完成了,那这不还是同步的吗? 还是我理解的有问题呢?

回答1:

你的感觉没有错,异步编程不能提高性能。异步编程只是提供一种简单的编程模型来提高系统的响应能力,比如,如果在UI线程上执行长时间IO操作,在操作完成之前界面就处在无法操作的状态。
可以提高性能的是并行技术,比如任务并行库(TPL,Task Parallel Library)、并行LINQ(PLINQ)等,这些技术可以充分利用CPU来提高计算性能。
一般来说,耗时的IO操作使用异步简化代码,耗时的计算操作使用并行来提高性能



回答2:

只是提高了线程的利用率,比如本来50个线程只能处理1000个并发,使用 async/await 后50个线程可以处理5000个并发



回答3:

和你有过同样的疑惑。
目前自己的理解是,比如服务端最大处理请求是100个线程,那么同步模式下,150个请求过来,就有50个请求需要等待执行。async await 模式下,正在执行的100个线程 可以空闲出来 处理后来的50个请求,前面100个请求异步完成后,再通过上下文切换到当前的100个线程,处理完后续的流程。工作线程是在不停的切换过程中提升了 并发效率。
而在单个请求中,async await是有线程上下文切换的性能损耗,所以在处理一个本来就很【快速】的逻辑例如读一个Redis缓存,那么性能会有比较显著的下降。



回答4:

这里 举一个这样的例子吧
去快餐店的时候,在你点完菜之后,其他人不会点任何东西,直到你吃完为止。使用async/ await,其他人可以在你点完菜之后下他们的订单,并且可以同时处理多个订单。



回答5:

如果你参与过高并发的项目,就会切身体会到异步的效果;

对于低并发的项目,绝大部分情况没有必要使用异步编程(除非要并行的执行多个耗时并且不需要返回结果的任务)



回答6:

首先 搞清楚异步的实现原理,楼上的都知道是系统的线程;

而使用 async和await 是更加高级的封装,不但简化了写法,而且注意这里不是Thread,而是Task;

而Task不等于Thread,所以反对了Dudu的一刀切说增加开销的说法 —— 不一定,如果线程池中的Thread没有被销毁,顺便拿来用,这种基本就算不得增加开销(因为可能Thread销毁比继续用  开销更大都说不定)。

传说的不一定是对的,异步是给你创造了线程池,但是你要相信IIS等等Server一定不会弱鸡到 过程不是Worker池(一般并发通讯都这么写,就不再称线程池了,差不多就是这个概念)模式,你应该知道IIS中有个线程设置的参数 —— 很明显你应该根据cpu及其虚拟化情况 以及 自己的应用(短时的多并发的和长时多运算的设置肯定不同)来设定,所以勿需过多担心 和 过多相信传言。

对于这种理解,我还是通常说法:你可以试试从Tcp构建HttpServer+MVC,你就明白了。

微软的封装和简化,对于进阶阶段,有时候务必去看看它的源码,就比如一个简单DbConnection,你在随便使用的时候觉得速度还不错,实际上你如果真正从通信连接对比,你才会知道比如Tcp你是不能当DbConnection那么玩的,那只是微软用空间换了时间,所以DbConnection可以随便玩,而真正的通信根本不会那么玩。