首页新闻找找看学习计划

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

0
悬赏园豆:30 [已解决问题] 解决于 2019-12-06 09:55

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

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

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

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

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

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

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

阿爆g的主页 阿爆g | 初学一级 | 园豆:15
提问于:2019-12-05 10:39
< >
分享
最佳答案
0

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

收获园豆:30
拓拓 | 菜鸟二级 |园豆:358 | 2019-12-05 13:48
其他回答(5)
0

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

dudu | 园豆:39706 (高人七级) | 2019-12-05 10:42

从单纯的性能角度看, async/await 反而增加了线程切换的开销

支持(1) 反对(1) dudu | 园豆:39706 (高人七级) | 2019-12-05 10:43

但是感觉说不通啊
比如我用POSTMAN 请求50次
同步的话 就是50个线程在执行50个请求
异步的话 就是100个线程执行50个请求 50个等待完成 50个执行上传
这不是增加了线程的开销吗?

支持(0) 反对(0) 阿爆g | 园豆:15 (初学一级) | 2019-12-05 10:50
0

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

xiaogui340 | 园豆:309 (菜鸟二级) | 2019-12-05 13:48

但是感觉说不通啊
比如我用POSTMAN 请求50次
同步的话 就是50个线程在执行50个请求
异步的话 就是100个线程执行50个请求 50个等待完成 50个执行上传
这不是增加了线程的开销吗?

支持(0) 反对(0) 阿爆g | 园豆:15 (初学一级) | 2019-12-05 15:54

@阿爆g: 提高了服务端的并发能力

支持(0) 反对(0) xiaogui340 | 园豆:309 (菜鸟二级) | 2019-12-05 16:13

@xiaogui340: 可是 明明只需要50个线程 但是用到了100个线程啊
还有50个也没事情干啊 在等待啊

就相当于 明明50个人能搞定 非要让100个人弄 还有50个闲着

支持(0) 反对(0) 阿爆g | 园豆:15 (初学一级) | 2019-12-05 17:51

@阿爆g:

最后一句理解有误,50个并没有闲着,而是去处理更多的请求去了;

真实情况,不是只有50个请求进来就完事了,而是持续的每秒都有50个请求进来。

支持(0) 反对(0) 码农搞事情 | 园豆:20 (初学一级) | 2019-12-05 18:12
0

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

初夏的阳光丶 | 园豆:484 (菜鸟二级) | 2019-12-05 13:48

但是感觉说不通啊
比如我用POSTMAN 请求50次
同步的话 就是50个线程在执行50个请求
异步的话 就是100个线程执行50个请求 50个等待完成 50个执行上传
这不是增加了线程的开销吗?

支持(0) 反对(0) 阿爆g | 园豆:15 (初学一级) | 2019-12-05 15:54

@阿爆g: 这么说吧,你去购物的时候,原本收银台只有一个,你需要等待前面的人结算完成之后才能轮到你去买单,但是现在突然增加了几个收银台,你就可以去换一个收银台结算。而你说的增加的线程的开销 就好比我多开几个收银台,需要聘请更多的人。需要支付更多的工资,但是你结算的速度快了。你的营业额也就多了起来。

支持(0) 反对(0) 初夏的阳光丶 | 园豆:484 (菜鸟二级) | 2019-12-05 15:58

@初夏的阳光丶: 感觉并不是这样理解的
等待的线程还是在等待闲着啊 并没有处理其它任务

明明只需要50个线程 但是现在用到了100个线程 还有50个也没事情干啊 在等待啊
就相当于 明明50个人能搞定 非要让100个人弄 还有50个闲着

支持(0) 反对(0) 阿爆g | 园豆:15 (初学一级) | 2019-12-05 17:52
0

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

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

码农搞事情 | 园豆:20 (初学一级) | 2019-12-05 17:44

我知道 多线程的好处 我这里只是想了解下
每个地方都用异步是否合理 因为看了些博主说 尽量用异步优化所有代码
不需要等待结果的任务 毕竟很少

支持(0) 反对(0) 阿爆g | 园豆:15 (初学一级) | 2019-12-05 17:49

用你举的例子;

比如我用POSTMAN 请求50次
同步的话 就是50个线程在执行50个请求
异步的话 就是100个线程执行50个请求 50个等待完成 50个执行上传
------------------------------------------------
假如你的IIS主线程,最高只能接受25个并发;
同步的话会有25个请求会返回失败;
而异步的话会开子线程来处理上传任务,主线程就可以去处理更多的请求;
------------------------------------------------
那么就结果就是50个并发请求进来,同步只能处理25个,而异步可以处理三四十个甚至更多;

支持(0) 反对(0) 码农搞事情 | 园豆:20 (初学一级) | 2019-12-05 17:54

@阿爆g:

所以说还是要看场景:
1.高并发
2.并行的多个耗时任务

效果上,再举一个例子,比如你的一台服务器配置很高,而IIS处理请求的能力是有限的;
用同步的的话,IIS最高可以响应1000个并发的时候,最多只能利用到50%的服务器处理能力;
而用异步的话,就可以利用到80%的服务器处理能力,去响应1500个并发;

支持(0) 反对(0) 码农搞事情 | 园豆:20 (初学一级) | 2019-12-05 18:07
0

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

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

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

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

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

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

花飘水流兮 | 园豆:10527 (专家六级) | 2019-12-06 02:26
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册