如何在不使用cgo的情况下将Go函数绑定到C调用?

时间:2015-01-24 16:56:39

标签: go cgo

在我正在研究的项目中,我需要使用Go中的一堆C函数。目前的实现是使用cgo实现这一目标,但这样做会产生巨大的性能影响,我试图将其删除。

  • cgo将所有C代码标记为系统调用,从而导致调度程序在需要时分配新线程。由于我的项目中大约80%的CPU时间用于繁重的C工作,这很快就会导致有很多线程(500+而不是GOMAXPROCS(= 8)),我的Linux内核没有同样多。
  • 做通常的限制器'方法(使用缓冲通道锁定cgo调用)会导致大量互斥,从而减慢程序速度。

我想继续使用Go作为这个项目,因为它是管理并发性的好方法。

我尝试过的事情:

  • entersyscall()中评论src/runtime/cgocall.go之类的内容(似乎没什么帮助,我更愿意避免修改Go代码)。
  • 将我的代码放在.c文件中并从Go调用它,而不是import "C"。这里没有运气 - 我无法调用该函数,当我将函数名称编写为package·function时,编译器抱怨文件中的无效字符。
  • 使用.s文件并将其写为程序集。我的asm并不是那么好,我无法弄清楚。

所以,我的问题是:如何使用Go中的C函数同时避免cgo的开销?

旁注:我知道为什么cgo将所有调用都标记为系统调用,但在这种特定情况下,我调用的函数不会阻塞锁或IO。

1 个答案:

答案 0 :(得分:0)

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

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


您可以使用Go项目中的C编译器编译C代码,但该编译器的优化程度几乎与gcc或clang一样,并且您的代码肯定会在将来中断Go的版本,因为该编译器不是任何稳定接口的一部分。