我错怪了goroutine-CSDN博客

前些天摸排wireguard-go的并发瓶颈,愧于对goroutine理解不深入,被误导,有必要记录以备忘。

wireguard-go为每一个peer开一个单独的goroutine,看起来像极了Apache的典型mpm,而boringtun则采用固定线程异步模型,颇像Nginx架构,从数据上看,boringtun吞吐碾压wireguard-go,身边又有人煽动加码,便得出结论,为每一个peer创建一个goroutine这种架构是不正确的。

很显然,这个结论是错误的。

理论上,创建万级别的goroutine毫无压力,而我只用不到10个甚至单peer进行测试,听闻几句话就把罪过归于goroutine,这是我的罪过,应该归于自己的无知。

回到问题和质疑的原点,为每个请求创建一个task是不正确的,原因在于每个CPU同时只能运行一个task,CPU数量固定,随着task的增加,切换开销线性增加。异步IO之所以好,因为task切换开销固定。我们知道,切换开销是业务处理的额外开销,越大越不好。

这就是我说的不要让请求去调度资源,而要让资源去调度请求。

现在看goroutine。goroutine并不是操作系统级的task,切换开销极小。理解了goroutine的G(goroutine)-P(processor)-M(machine)模型,就会发现它事实上和异步事件模型一致:

  • 固定数量的M上跑不固定数量的G,G之间的切换开销与查找无异。

异步事件模型中,固定数量的线程处理所有被激活的请求,这些请求或被轮询处理,或排以优先级,这与goroutine的方式无异,goroutine的方式只是将“或轮询或优先级处理”这件事交给了Runtime库,程序员只需要关注自己的业务逻辑即可,即写一个前面加上go关键字的func。

goroutine的调度,本质上就是异步事件驱动的多请求处理的轮询。

golang好在,它甚至让你无法使用错误的方式处理并发,不信试试看,如何写一个程序,让操作系统级别的切换开销随着请求的数量线性增加。

无论怎么样,系统级task的数量都是一定的(more or less),就算100万并发,也不会有100万系统级task,系统级task永远都是CPU数量级的,如果用CPU数量级的task处理100万的并发,就是goroutine的调度问题了,而调度的本质就是查找,这个查找的开销,便和系统task切换无关了。

这便和下面的文章统一了:
https://zhuanlan.zhihu.com/p/492863461

因此,goroutie不足以构成并发瓶颈,它甚至是优势,虽然性能可能达不到标准异步模型,但它大大简化了编程难度,门槛极低。性价比还是优于rust的。

当关注纠结某件事时,偏见便侵入了,比方说当已有事实证据指向某个方向时,旁人只需轻微一点,你便很容易将所指之处作为根本去试图揭露,这便是偏见之害。若对goroutine没有深入理解,便很容易将per peer a goroutine等同于per client a thread/process,如果此时你还不敢下定论,只需有人也这么一说,便判定无疑了,但事实上,据此下的结论其效果正好相反。所以,不要针对自己不了解的任何东西下任何结论。

浙江温州皮鞋湿,下雨进水不会胖。

原文链接: https://blog.csdn.net/dog250/article/details/124168177

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    我错怪了goroutine-CSDN博客

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/405559

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月26日 上午9:16
下一篇 2023年4月26日 上午9:17

相关推荐