【发布时间】:2015-03-23 13:19:04
【问题描述】:
在我正在进行的一个项目中,我需要使用 Go 中的一堆 C 函数。当前的实现是使用 cgo 来实现这一点,但这样做会产生巨大的性能影响,我正在尝试消除它。
- cgo 将所有 C 代码标记为系统调用,从而使调度程序在需要时分配一个新线程。由于我的项目中大约 80% 的 CPU 时间都花在了繁重的 C 工作上,这很快就会导致有很多线程(500+ 而不是
GOMAXPROCS(= 8)),而我的 Linux 内核不太喜欢这些线程. - 执行通常的“限制器”方法(使用缓冲通道锁定 cgo 调用)会导致大量互斥体,从而减慢程序速度。
我想继续在这个项目中使用 Go,因为它是管理并发的好方法。
我尝试过的事情:
- 注释掉
src/runtime/cgocall.go中的entersyscall()之类的内容(似乎没有多大帮助,我宁愿避免修改Go 代码)。 - 将我的代码放在一个 .c 文件中并从 Go 中调用它,不带
import "C"。这里没有运气 - 我无法调用该函数,当我将函数名称写为package·function时,编译器抱怨文件中的字符无效。 - 使用 .s 文件并将其编写为程序集。我的 asm 不是很好,我想不通。
所以,我的问题是:如何在避免 cgo 开销的同时使用 Go 中的 C 函数?
旁注:我知道为什么 cgo 将所有调用标记为系统调用,但在这种特定情况下,我调用的函数不会阻塞锁或 IO。
【问题讨论】:
-
我认为 gccgo 在调用 C 代码时的开销可能会更少。您可以尝试对此进行进一步研究。