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