4

在我正在进行的一个项目中,我需要使用 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。

4

1 回答 1

0

你想做的事情是不可能的。C 代码具有高开销是有原因的,即 C 代码使用不同的 ABI(平台的本机 ABI),它不支持 Go 使用的短堆栈。因此,每当 Go 代码调用 C 代码时,都必须在线程本机堆栈上继续执行。这会导致您看到的开销。没有办法消除这种开销。想一想:如果不需要开销,它就不会存在。

如果不知道你的程序是什么样子,很难说你应该做什么。

于 2015-01-24T17:13:36.397 回答