【问题标题】:How to bind Go functions to C calls without using cgo?如何在不使用 cgo 的情况下将 Go 函数绑定到 C 调用?
【发布时间】: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 代码时的开销可能会更少。您可以尝试对此进行进一步研究。

标签: go cgo


【解决方案1】:

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

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

【讨论】:

  • 你的逻辑完全有缺陷。人们不会一直移除不需要的开销,仅仅是因为他们不需要花费精力来移除它。
  • 对,所以你的意思是 cgo 中的额外堆栈是不可避免的 - 我同意。但这并不意味着不能消除所有其他开销
  • @TomvanderWoerdt duh... 所有额外的开销都需要它才能正常工作。
  • @FUZxxl:“您可以使用 Go 项目中的 C 编译器编译您的 C 代码”。 Go 1.5 删除了 Go C 编译器。
  • @peterSO 这就是为什么我说“你的代码肯定会在 Go 的未来版本中崩溃”
猜你喜欢
  • 2023-03-21
  • 2018-10-16
  • 2021-02-20
  • 2012-11-30
  • 1970-01-01
  • 2021-08-08
  • 2014-12-31
  • 1970-01-01
  • 2015-07-19
相关资源
最近更新 更多