为什么cgo的性能这么慢?我的测试代码有问题吗?
我正在做一个测试:比较cgo和纯Go函数的执行时间,每个函数运行一亿次。与Golang函数相比,cgo函数需要更长的时间,我对此结果感到困惑。我的测试代码是:
package mainimport (
"fmt"
"time"
)
/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void show() {
}
*/
// #cgo LDFLAGS: -lstdc++
import "C"
//import "fmt"
func show() {
}
func main() {
now := time.Now()
for i := 0; i < 100000000; i = i + 1 {
C.show()
}
end_time := time.Now()
var dur_time time.Duration = end_time.Sub(now)
var elapsed_min float64 = dur_time.Minutes()
var elapsed_sec float64 = dur_time.Seconds()
var elapsed_nano int64 = dur_time.Nanoseconds()
fmt.Printf("cgo show function elasped %f minutes or \nelapsed %f seconds or \nelapsed %d nanoseconds\n",
elapsed_min, elapsed_sec, elapsed_nano)
now = time.Now()
for i := 0; i < 100000000; i = i + 1 {
show()
}
end_time = time.Now()
dur_time = end_time.Sub(now)
elapsed_min = dur_time.Minutes()
elapsed_sec = dur_time.Seconds()
elapsed_nano = dur_time.Nanoseconds()
fmt.Printf("go show function elasped %f minutes or \nelapsed %f seconds or \nelapsed %d nanoseconds\n",
elapsed_min, elapsed_sec, elapsed_nano)
var input string
fmt.Scanln(&input)
}
结果是:
cgo show function elasped 0.368096 minutes or elapsed 22.085756 seconds or
elapsed 22085755775 nanoseconds
go show function elasped 0.000654 minutes or
elapsed 0.039257 seconds or
elapsed 39257120 nanoseconds
结果表明,调用C函数比Go函数要慢。我的测试代码有问题吗?
我的系统是:mac OS X 10.9.4(13E28)
回答:
正如您所发现的那样,通过CGo调用C / C
++代码的开销相当大。因此,一般而言,最好是尽量减少拨打CGo的次数。对于上面的示例,与其在循环中重复调用CGo函数,不如将循环向下移动到C。
Go运行时如何设置其线程可能会破坏许多C代码的期望,有很多方面:
- Goroutine在相对较小的堆栈上运行,通过分段堆栈(旧版本)或复制(新版本)来处理堆栈增长。
- Go运行时创建的线程可能无法与
libpthread
的线程本地存储实现正确交互。 - Go运行时的UNIX信号处理程序可能会干扰传统的C或C ++代码。
- Go重用OS线程来运行多个Goroutine。如果C代码调用了阻塞系统调用或以其他方式独占了线程,则可能对其他goroutine有害。
由于这些原因,CGo选择了在传统堆栈中设置的单独线程中运行C代码的安全方法。
如果您来自Python之类的语言,那么用C重写代码热点作为加速程序的一种方法并不少见,您会失望的。但是,与此同时,等效的C和Go代码之间的性能差距要小得多。
通常,我保留使用CGo与现有库进行接口,可能还使用小型C包装函数,这些函数可以减少我需要从Go进行的调用次数。
以上是 为什么cgo的性能这么慢?我的测试代码有问题吗? 的全部内容, 来源链接: utcz.com/qa/430652.html