libaco: 一个极速的轻量级 C 非对称协程库 🚀 (10 ns/ctxsw + 一千万协程并发仅耗内存 2.8GB + Trending)

2018-07-17 20:25:28 +08:00
 hnes

项目链接:https://github.com/hnes/libaco

大家好,下面是这个项目的简要介绍:

上文中的"最快"指的是在满足 Sys V ABI Intel386 或者 AMD64 约束下最快的上下文切换实现。

中文文档正在做最后的 review,今晚或者明天发布,敬请期待 :D

下面是前几天在 Reddit 上讨论的帖子列表:

热烈欢迎大家的问题和建议 ;-)

Edit: 添加项目链接。

9090 次点击
所在节点    分享创造
62 条回复
hnes
2018-07-18 09:11:14 +08:00
@pymumu 另外,10ns 在 3.5GHz 的 CPU 上大概只有 35 个时钟周期,这仅仅约为一个 32 位整型除法指令的耗时。


Intel Haswell:

instruction latency (core clock cycles)
add 1
mul 3
div r32 22-29
div r64 32-96
hnes
2018-07-18 09:21:18 +08:00
@missdeer 目前支持所有 ABI 规范为 Sys V ABI Intel386 以及 AMD64 的操作系统,包括所有 Unix 系的操作系统,比如 Linux, BSD, MacOS, Minix, SunOS...等等。
具体只要查询一下目标系统的 ABI 规范是否为 Sys V ABI Intel386 或 AMD64 即可 ;-)
hnes
2018-07-18 09:24:12 +08:00
@missdeer 编译器的话目前已知可以用的有 Gcc 和 Clang,正常情况下编译工具链只要包含 C 编译器和汇编器(还有链接器)应该都没有问题,当然具体的可以尝试一下哈。
hnes
2018-07-18 09:25:59 +08:00
@missdeer 后面也会加入对 ARM 的支持,以及对 Windows 操作系统的支持( Microsoft ABI ),敬请关注 :D
pymumu
2018-07-18 09:33:37 +08:00
@hnes 你总结的没错,ucontext 上下文切换是相对比较耗时的。
posix 移除此接口原因是 makecontext 函数与 ISO C 不兼容,这个两个有差别吗?

c 的协程对编程的要求比较高,如果切换不合理,一不小心性能反而会下降,并且协程如果调用系统调用阻塞了,那整个任务也就挂住了。并且现在多核的情况下,协程并不能有效利用 CPU。

协程的本意是用户态调度,目的是让写代码的人,感知不到切换,也就是一个上下文做一件事情,没有状态,这是对比异步 IO+多路复用来说的。
但我觉得对于高并发程序,还是应该使用异步 IO+多路复用的模式来写,因为底层 API 对异步 IO 已经支持很好了。支持几十万,上百万处理不是问题。

go routine 在这方面其实优化的很好,不仅保证了写代码的便捷,同时保证了性能。

如果这个库能让 C 有类似的能力的话,就很好了。否则也只是特定的业务使用,并且还要小心使用。
tt67wq
2018-07-18 09:34:27 +08:00
碉堡了!
feverzsj
2018-07-18 09:34:51 +08:00
可以和 vc 现在支持的 c++ stackless coroutine 做下性能比较
hnes
2018-07-18 09:51:24 +08:00
@pymumu 感谢你的建议 :D

> c 的协程对编程的要求比较高,如果切换不合理,一不小心性能反而会下降,并且协程如果调用系统调用阻塞了,那整个任务也就挂住了。

是这样的,但是协程的使用目标一般都是借此实现类似 ngx lua cosocket 的这种编程模型的(用同步的语义书写异步程序,彻底摆脱所谓的 callback hell ),后面我还会继续放出来一个满足这个要求的库,可以认为是一个 C 语言实现的“ Golang ”定制版(砍掉 golang 中不适合高性能高并发低消耗场景的一些东西,尤其是复杂重量级的调度器和 GC 逻辑) :D

ngx lua cosocket: https://moonbingbing.gitbooks.io/openresty-best-practices/ngx_lua/whats_cosocket.html

> 并且现在多核的情况下,协程并不能有效利用 CPU

但是,为什么不能是多线程+协程(协程数 : 线程数 == C*T : T )呢?

> 如果这个库能让 C 有类似的能力的话,就很好了。否则也只是特定的业务使用,并且还要小心使用。

是的,后面将会放出一个这样的库,完全满足你的设想 :D

(之所以打算两个分开放出来,是因为我认为协程库是很多场景中都有很大用处的一个组件,分开放出来应该对使用者们更有利,可以自由的定制选择)
hnes
2018-07-18 09:52:20 +08:00
@tt67wq 感谢支持哈 ;-)
tommydong
2018-07-18 09:56:43 +08:00
@hnes 这种情况在 iass 的 LB 服务里面的确需要 ,我们以前就是基于 dpdk 做的。dpdk 是绕过了 linux 的内核协议栈,这个库不知道有没有做这方面的工作
hnes
2018-07-18 09:57:30 +08:00
@feverzsj 感谢你的提议,有机会一定尝试测试下 :D
hnes
2018-07-18 10:04:24 +08:00
@tommydong 之前研究过集群前端调度器很长时间,不过现在我没有在从事这方面的工作。

但是 libaco 是通用的,自然可以自由的与 dpdk 结合在一起,后续我还会放出来一个类 Golang 的 C 多线程网络库(前面给 pymumu 的回复中有具体的描述),只要修改一下底层 socket 的 API,应该就能直接的用在 dpdk 上面了。
hnes
2018-07-18 10:07:01 +08:00
@tommydong 当然如果是要做 tcp/udp 层的编程,还要解决好用户空间协议栈的问题 :D
deadEgg
2018-07-18 19:02:57 +08:00
支持 ,以前被 GIL 搞的要死才用协程。

请教楼主现在做这个库是为了解决什么场景的问题呢。还是说去解决一些性能上的问题呢?
hnes
2018-07-18 20:40:38 +08:00
@deadEgg 非常感谢你的支持 ;-)

> 现在做这个库是为了解决什么场景的问题呢。还是说去解决一些性能上的问题呢?

是的,主要是性能上的问题,但是,也可以认为是某种场景的解决方案。

场景:

高性能(应该接近极致)、高并发(百万数量级)和对内存使用效率(应该接近极致)要求很高的应用。

我们要实现一个核心的网络服务,最初考察使用 go 来完成,后来经过了一段时间的考察实验,甚至已经写了很多的 go 代码,发现完全满足不了我们需求( GC、多线程切换损耗、内存消耗、调度器相关的等等相关的问题),最后还是决定选择使用 C 来实现。

而且在网络编程时又不想过度的使用 callback 去手写状态机,所以最好的方法就是实现一个“用 C 定制的 golang ”,去掉 golang 对高性能高并发应用场景不利的的东西,在 C 的极速与 golang 的易用之间找到一个最适合我们应用场景的平衡点,而 libaco 就是这个项目中的核心组件--协程库的实现,后续将会把全部的实现代码都放出来,敬请期待 :D

PS:

我也是 go 的爱好者,如果遇到要求不是这么高的场景,还是非常乐意选择 go 的。
wtcoder
2018-07-19 02:44:07 +08:00
楼主牛人!小公司表示看了您作品的介绍,才发现~ 我们最大的性能瓶颈是带(Que)宽(Qian)...
hnes
2018-07-19 08:00:28 +08:00
@wtcoder 十分感谢你的鼓励 ;-)

libaco 是开源的,热烈欢迎贵公司在生产环境中使用它,中间如果遇到任何的问题都可以发 Issue 大家一起来探讨哈 :D
yulon
2018-07-19 16:01:38 +08:00
libco 里面居然还有这种操作,我被秀到了_🤣」∠)_
hnes
2018-07-19 16:49:34 +08:00
@yulon 刚刚看到时确实比较惊讶,后来想了下,可能是代码贡献者当时想要省掉手写寄存器偏移地址的这个工作吧...
pkv
2018-07-19 17:45:52 +08:00
有两个小问题:
1. 有没有在生产环境使用?
2. 有没有和过其它 C/C++ 协程库的对比结果,不只是自己跑的 benchmark,如对比微信使用的 https://github.com/Tencent/libco

谢谢~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/471755

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX