这几年,似乎服务器开发领域一直在向异步发展。
一开始java系netty开始流行nio 从nodejs 开始,开始流行promise,回调地狱迫使它支持了async await golang看不下去了,用CSP模型 实现了彻底的异步化 最后出场的Rust贯彻零开销概念,也实现了基于future的async await
后来 一些开源库作者蠢蠢欲动,
async_std 欲成为rust的异步标准库,tokio凭借mio以及大名鼎鼎的actix-web谁与争锋。 后起之秀may 欲实现go的CSP模型却苦于固定容量栈
最后,作为开发者的你 大概使用rust也懵逼了吧??? 比如我,我希望异步库性能高,也希望0开销,似乎2者不可兼得。
例如,基于future的tokio 和基于csp模型的may性能上肯定有一点点差距, 在我看来,IO的时间越长,future的优点体现出来了,它可以hold住更多的IO同时保持低消耗。 但是 IO的时间如果越短,future的弱点就出来了,反而基于线程模型或者CSP模型的吞吐量更快更高
忽然在想,是否能有基于时间评估的异步运行时呢,例如500ms时间内在线程池里执行,超过500ms移动到协程池里执行
评论区
写评论要测切换开销也是多个线程/协程切,而不是单个在那边 yield。。。这能一样么。
”但是IO的时间如果越短,future的弱点就出来了“ 有啥理论依据?假设一个 io 瞬间完成,无论操作系统还是 async runtime 都有能力在原地继续执行,没啥本质区别。
测试数量提高到10万(数量多一些),换windows10测试,并且使用--release
--
👇
zhuxiujia: 改了下实现算法
--
👇
zhuxiujia: 4核,我这里测smol和async_std 差不了多少
--
👇
vimcdoe: 补上smol
https://github.com/vimcdoe/yield_now_test
cpu 多少核的 我这里测的smol最快
4核,我这里测smol和async_std 差不了多少
--
👇
vimcdoe: 补上smol
https://github.com/vimcdoe/yield_now_test
cpu 多少核的 我这里测的smol最快
补上smol
https://github.com/vimcdoe/yield_now_test
cpu 多少核的 我这里测的smol最快
补上async_std的yield
--
👇
zhuxiujia: 你确定???
--
👇
gwy15: 把 sleep_for 改成
tokio::task::yield_now()
和std::thread::yield_now()
,现在是纯粹切换上下文了,结果:https://gist.github.com/gwy15/0cfdae1dedf059252202a9b15c246386
你确定???
--
👇
gwy15: 把 sleep_for 改成
tokio::task::yield_now()
和std::thread::yield_now()
,现在是纯粹切换上下文了,结果:https://gist.github.com/gwy15/0cfdae1dedf059252202a9b15c246386
把 sleep_for 改成
tokio::task::yield_now()
和std::thread::yield_now()
,现在是纯粹切换上下文了,结果:https://gist.github.com/gwy15/0cfdae1dedf059252202a9b15c246386
测试不算特别严谨,但是反应出tokio 的02版本调度性能不给力呀。比go和async_std差一倍。 正规的IO测试应该发起一个模拟http请求之类的。总的来说,短IO肯定是线程更快一点点
--
👇
gwy15: 你这就一个线程,反复等 delay,然后把总时间除以等待的总时间,误差也太大了。
tokio 的
tokio::time::delay_for
很清楚地写了,如果要比较“上下文切换”的速度,应该比较的是高数量的线程/协程切换时间,而不是单个线程反复等低精度的计时器。
你这就一个线程,反复等 delay,然后把总时间除以等待的总时间,误差也太大了。
tokio 的
tokio::time::delay_for
很清楚地写了,如果要比较“上下文切换”的速度,应该比较的是高数量的线程/协程切换时间,而不是单个线程反复等低精度的计时器。
再试一下golang的模拟
--
👇
zhuxiujia:
--
👇
gwy15: 你做个减法啊, 协程是 4309-2 = 4307,线程是 17352-312=17040……
--
👇
zhuxiujia: 代码应该改为,已经创建好的1000个线程的线程池和协程池可以不需要预备。
--
👇
gwy15: 写了个 (在我看来完全没必要的) benchmark,协程切换上下文的速度在楼主说的“短IO=1ms”的情况下完虐线程。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4e7908f8eeb145686711c27bb70e3ea9
那么楼主的结果呢?
--
👇
gwy15: 你做个减法啊, 协程是 4309-2 = 4307,线程是 17352-312=17040……
--
👇
zhuxiujia: 代码应该改为,已经创建好的1000个线程的线程池和协程池可以不需要预备。
--
👇
gwy15: 写了个 (在我看来完全没必要的) benchmark,协程切换上下文的速度在楼主说的“短IO=1ms”的情况下完虐线程。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4e7908f8eeb145686711c27bb70e3ea9
那么楼主的结果呢?
你做个减法啊, 协程是 4309-2 = 4307,线程是 17352-312=17040……
--
👇
zhuxiujia: 代码应该改为,已经创建好的1000个线程的线程池和协程池可以不需要预备。
--
👇
gwy15: 写了个 (在我看来完全没必要的) benchmark,协程切换上下文的速度在楼主说的“短IO=1ms”的情况下完虐线程。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4e7908f8eeb145686711c27bb70e3ea9
那么楼主的结果呢?
代码应该改为,已经创建好的1000个线程的线程池和协程池可以不需要预备。
--
👇
gwy15: 写了个 (在我看来完全没必要的) benchmark,协程切换上下文的速度在楼主说的“短IO=1ms”的情况下完虐线程。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4e7908f8eeb145686711c27bb70e3ea9
那么楼主的结果呢?
异步性能需求高请用mio或者polling。在上面配什么executor和reactor都可以,配多个划分优先级也可以。tokio和async-std主要是方便易用,适合大多数应用场景。
你这代码创建10000个线程和协程,创建过程肯定线程吃亏呀,因为协程是0开销的,没有申请栈空间
👇
gwy15: 写了个 (在我看来完全没必要的) benchmark,协程切换上下文的速度在楼主说的“短IO=1ms”的情况下完虐线程。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4e7908f8eeb145686711c27bb70e3ea9
那么楼主的结果呢?
写了个 (在我看来完全没必要的) benchmark,协程切换上下文的速度在楼主说的“短IO=1ms”的情况下完虐线程。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4e7908f8eeb145686711c27bb70e3ea9
那么楼主的结果呢?
你可以简单做个benchmark对比,就线程池(最大6线程)和future运行时(最大6线程) 1000个请求 性能对比,反正我这边测试结果是 IO时间短(例如1ms),线程池响应速度快,处理量也更多,时间更短。 如果io时间设置的很长,比如60秒,那么线程池里面,到第6个任务后面全是阻塞了,新IO任务进不来。 而future运行时则把所有的IO请求吃进来了,在上下文切换。
--
👇
Mike Tang: 你确定 IO 短的时候,csp或线程池更高效?
多短?1ms都长了吧?
不明白IO的时间如果越短,future的弱点就出来了 有什么原理上的原因?
你确定 IO 短的时候,csp或线程池更高效?
多短?1ms都长了吧?
比如,你发起一条http请求,耗时5秒这就是io时间长,耗时100ms 这就是耗时短呀
--
👇
Mike Tang: IO时间长短啥意思?