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 条回复
lekai63
2018-07-17 20:28:34 +08:00
沙发。看起来很吊的样子
hnes
2018-07-17 20:31:26 +08:00
@lekai63 感谢你的支持 :D
byteli
2018-07-17 20:39:43 +08:00
板凳,支持一下,收藏了有空看看。文档看起来非常优秀
hnes
2018-07-17 20:43:10 +08:00
@byteli 十分感谢 :D 文档确实是花了很大的心血,希望能对使用和研究协程的朋友们有用处 ;-)
Kilerd
2018-07-17 21:43:53 +08:00
6666. mark 最近刚好想研究一下协程在底层的具体实现。有空读下代码。
hnes
2018-07-17 21:51:06 +08:00
@Kilerd 十分感谢哈 ;-)
协程的实现以及应用确实非常有趣,希望这个项目的代码以及文档能够对你有用处,如果遇到任何问题可以发 Issue 大家一起讨论 😁
icylord
2018-07-17 22:47:15 +08:00
厉害,协程一直都处于看不懂的状态
hnes
2018-07-17 23:23:24 +08:00
@icylord 感谢 :D

协程的根本思想应该是比较清晰的。

但如果要具体地去实现一个协程库,需要对系统的 ABI 规范很熟悉(重点是二进制函数调用中寄存器与栈的一些约定细节),也需要些汇编(重点是函数调用约定部分)的基础知识(这部分其实比较简单,如果对计算机体系结构比较熟悉的话初学它可能一两个小时就学会了)。

比如腾讯的 libco 中就有一个[bug]( https://github.com/Tencent/libco/issues/90),在微信的生产系统中隐藏了五年多都没有被发现(从它的 Github 代码仓库中看是如此),就是因为在实现的时候没有严格遵守 Sys V ABI 的规范导致的。

libaco 项目中的文档还是比较齐全的,而且还有严格的数学证明,希望对你有所助益哈 ;-)

当然,如果有问题的话,可以发 Issue 大家一起探讨,这样会更加有乐趣 :D
hnes
2018-07-17 23:25:17 +08:00
实在抱歉,纠正:

链接: https://github.com/Tencent/libco/issues/90

> 比如腾讯的 libco 中就有一个 bug,在微信的生产系统中隐藏了五年多都没有被发现(从它的 Github 代码仓库中看是如此),就是因为在实现的时候没有严格遵守 Sys V ABI 的规范导致的。
lsmgeb89
2018-07-17 23:29:51 +08:00
有证明厉害,看看
tommydong
2018-07-17 23:39:16 +08:00
好奇的问句 1000 万的协程并发的应用场景?
tommydong
2018-07-17 23:39:54 +08:00
还是很厉害👍 要赞一个
jedihy
2018-07-18 01:20:18 +08:00
厉害
est
2018-07-18 01:45:51 +08:00
厉害
hnes
2018-07-18 08:36:34 +08:00
@tommydong 早上好,实在不好意思哈,昨天回复完上一位朋友的留言后就去睡觉了 ;-)

> 1000 万的协程并发的应用场景?

一个简短的总结就是,高性能、高并发和对内存使用效率要求很高的场景(当然,对这三点要求低些的应用肯定都是能用的,哈哈)。

一个最典型的案例就是网络服务程序,比如大型集群的前端调度器(单机并发数百万数量级,比如像以用户空间 dpdk 实现的 Director ),以及像 Nginx、Redis 这样的对以上三点要求很高的网络服务基础设施。

穿插一些相关的:

Golang 也很棒,但是却不太适合上面的场景,与 C/C++相比,Golang 的编译器的优化有较大的提升空间(且 GCC 已经有 30 多年的演进历史),语言的抽象层过于重量级( Golang 的核心开发小组为了用户的易于使用已经牺牲了太多的性能,在多线程高并发的场景下,调度器损耗太大,当然还有 GC 问题...)。

我其实也是 Golang 的长期用户和爱好者,如果碰到对这些指标要求不是很高的服务程序我还是会很乐意选择 Golang 的 ;-)
hnes
2018-07-18 08:40:16 +08:00
@lsmgeb89 感谢 :D 我也非常喜欢数学证明,写的时候也非常地开心。
hnes
2018-07-18 08:49:45 +08:00
@jedihy @est 十分感谢 :D 希望这个项目能够对朋友们有些用处 ;-)
pymumu
2018-07-18 08:50:35 +08:00
这个轮子对比 libc 的 ucontext 协程有什么优势?
missdeer
2018-07-18 09:03:45 +08:00
支持什么系统?什么编译器?
hnes
2018-07-18 09:07:33 +08:00
@pymumu

libaco 的上下文切换`acosw`耗时为 10ns (RHEL-7.5 & c5d.large on AWS),而 ucontext 中有关于 sigprocmask 的系统调用(而且对于应用来说,在绝大多数情况下这个 Syscall 是没有存在必要的),时间数量级在 200-300ns 之间,而且系统调用会给当前运行线程带来严重的 cache-miss,会进一步影响线程的运行,所以,真正注重性能的网络应用是不会选择使用 ucontext (还有一点,ucontext 中的 setcontext 等等函数已经从 POSIX 标准中移除)。

PS:

$ man 3 setcontext
...
CONFORMING TO
SUSv2, POSIX.1-2001. POSIX.1-2008 removes the specification of getcontext(), citing portability issues, and recommending that applications be rewritten to use POSIX threads instead.
...

另外,OpenBSD 中并没有实现 ucontext。

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

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

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

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

© 2021 V2EX