libcsp: 一个 10 倍于 Golang 的高性能 C 语言并发库

2020-04-07 09:10:07 +08:00
 Lime

特性:

Github: https://github.com/shiyanhui/libcsp

文档: https://libcsp.com (英文, 中文文档找时间写一下)

6023 次点击
所在节点    分享创造
24 条回复
reus
2020-04-07 09:17:06 +08:00
“10 倍”是怎么测试的?
web 场景里,大并发下延迟的分布如何?
Lime
2020-04-07 09:33:01 +08:00
@reus 看文档
mritd
2020-04-07 10:01:10 +08:00
问题是为什么对比 Go 呢🤔
Lime
2020-04-07 10:21:48 +08:00
@mritd 因为两者都是基于 CSP 并发模型 而 C 语言并发库目前实现绝大部分都是单线程 不能利用多核
reus
2020-04-07 10:49:17 +08:00
@Lime https://github.com/shiyanhui/libcsp/blob/master/benchmarks/sum.go 这里的写法不是 go 典型的做法,没人会无限量地开启 goroutine 的,更何况是这种生存期很短的 goroutine 。goroutine 的创建和调度都有开销。
Lime
2020-04-07 11:14:07 +08:00
@reus 对 Benchmark 的目的就是比较极端情况下的性能 libcsp 同样会不停的的创建 /调度 /运行 /销毁 process(对应 goroutine)
wslzy007
2020-04-07 11:44:49 +08:00
毕竟多核下 m:n 模式会有多线程,任务间线程安全如何保障?任务自己 lock/unlock ?频繁上下文切换会迅速抵消调度的高性能;
Lime
2020-04-07 11:58:17 +08:00
@wslzy007 这就涉及到具体调度实现了 可以看下 src/sched.c
wslzy007
2020-04-07 12:04:10 +08:00
看了,如果只是比较调度性能的话,建议找一个实现良好的 thread-pool 进行对比测试估计意义更大一些。
Lime
2020-04-07 12:11:12 +08:00
@wslzy007 赞 有时间我对 libcsp 和 thread-pool 做一下对比
wslzy007
2020-04-07 12:18:43 +08:00
事实上最后的性能差异更多的集中在两个方面:
1 、调度策略(尽可能保证无上下文切换;兼顾快、慢任务,任务优先级考虑。。。)
2 、lock-free queue 性能
fakevam
2020-04-07 14:26:18 +08:00
1. mutex 的实现太暴力了,有些场景会很糟糕,怎么退化 mutex 是需要考虑的,退化 mutex 以后这个问题就复杂化了
2. 调度优先级也过于暴力,考虑性能比较多,考虑公平性不够,可能出现调度饥渴,另外 task 的亲和性问题貌似没看到太多的处理,计算敏感的场景下,task 的亲和性还是很重要的
3. 准备下配套的 gdb 调试脚本,否则切换协程以后压根没法调试,不是每个人都会去解析那一堆的上下文的
4. 一个 epoll 大概率是不够的,epoll 在某些场景下性能退化很严重的,有些东西比较糟心

抛开这些,代码质量还是不错的
不过我还是不推荐玩这种东西,受限太严重了,需要性能的时候,一切都需要自己控制,不需要的时候,golang 的那套足够覆盖了
Lime
2020-04-07 15:48:35 +08:00
@fakevam 评价的很独到客观了 眼力很厉害 赞

1. mutex 这个 避免不了 如果不用的话 可能会有更大的代价 实现的时候仅用在那些很大概率不会冲突的地方 后续会考虑看有没有添加 RWmutex 的必要

2. 在"调度公平"这个问题上 简单来说 libcsp 维护两种队列 一个是全局队列 一个是本地队列 挂起的 process(上下文)放到本地队列末尾 每次从本地队列头部取新的要执行的 process libcsp 每隔一定固定次数就会去全局队列去取 所以"调度饥渴"问题不会出现 对于在全局队列的 processes 确实会有调度公平的问题 另外 task 亲和性目前实现也确实没有考虑

3. 是的 这个后续会添加上

4. 这个后续也会改进

libcsp 还需要进化 比如支持更多架构(比如 arm)/支持 C++/支持 clang 编译器 /支持更多 OS 等
baoyexi
2020-04-07 17:41:51 +08:00
@fakevam 您好,关于退化 mutex 方面是否有经验可以分享一下,最近遇到了 mutex 占用资源的问题一直没有什么头绪。
fakevam
2020-04-07 17:57:59 +08:00
@baoyexi
mutex 这个东西不要想着去优化锁本身的性能
1. 锁内部的代码,是否足够轻便和必要
2. 锁冲突的路径是不是可以考虑转移,把锁转移到一个数据流更加冷的路径下去

@Lime mutex 自己做的成本很高,这是我不推荐用协程的关键原因,因为没有人知道谁会怎么跑你在你的任务框架上,协程的锁理论需要做锁膨胀才是最优解

调度饥渴就是调度公平问题,考虑一个很经典的场景,N 个人去 xxx 部门开证明,有 M 个步骤,每个步骤都需要串行,最后的结果就是第一个人处处优先,最后一个特别慢,明显这种情况下,最后一个人可能是很不满意的
内核的 cfs 调度其实某些角度就是为了解决这个问题,epoll_wait 的 event,也可能导致类似的问题,我只开个头,你自己思考
kingddc314
2020-04-07 17:59:33 +08:00
赞一个
fakevam
2020-04-07 17:59:57 +08:00
@baoyexi 补充一点,lock-free 对于 99.99%的代码来说是屠龙之术
一把锁只有没有办法降低冲突了,才会考虑 lock-free,否则优先考虑怎么避免冲突
waruqi
2020-04-07 22:47:48 +08:00
赞!可以考虑下用 xmake 来维护和跨平台编译哦
Fu4ng
2020-04-07 23:24:24 +08:00
很赞的项目,已 start,打算这几天闲下来,仔细看下。
Fu4ng
2020-04-07 23:29:04 +08:00
对了,您的“hero”项目的中文 readme 中的 bthub.io 连接似乎失效了

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

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

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

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

© 2021 V2EX