cgo

command
v0.0.0-...-ba01d29 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 25, 2025 License: MIT Imports: 6 Imported by: 0

README

核心原理

在Go中调用C函数时,runtime.cgocall中调用entersyscall脱离调度器管理。runtime.asmcgocall切换到m的g0栈,于是得到C的运行环境。

在C中调用Go函数时,crosscall2解决gcc编译到6c编译之间的调用协议问题。cgocallback切换回goroutine栈。runtime.cgocallbackg中调用exitsyscall恢复Go的运行环境。

benchmake CGO

taskset -c 1 go test -run=^$ -bench BenchmarkCgoC github.com/dajuguan/go/codes/basics/cgo -v 

BenchmarkCgoCCallGoOverhead                 14120484                86.15 ns/op  (Go=>c=>go, exclude handle (cgo type) init)
BenchmarkCgoCCallGoOverheadHandle           2772770                 410.7 ns/op (Go=>c=>go, include handle (cgo type) init)
BenchmarkCgoCCallGoOverheadRegistry         13506428                88.21 ns/op (Go=>c=>go, exclude handle(registry type) init)
BenchmarkCgoCCallGoOverheadRegistryHandle   9940838                 119.7 ns/op (Go=>c=>go, include handle(registry type) init)
BenchmarkCgoCall                           34297670                 35.16 ns/op
  • 创建Cgo handle的开销是320ns (410-86 = 314), 用registry创建handle的时间只需要30ns (119-88=31)
  • 通过Cgo handle从C调用Go的overhead是50ns (86-35 = 51)
  • 通过Cgo, 从Go call C的overhead是~40ns

benchmark

taskset -c 1 go test -run=^$ -bench=. -v -tags=llvm20

BenchmarkGoSlicePassToCAndSetmem-28             15674406                74.87 ns/op
BenchmarkCAllocAndSetmem-28                     23777948                52.18 ns/op
BenchmarkGoSlicePassToCAndLLVMSetmemLoop-28     18198148                64.05 ns/op
BenchmarkGoSlicePassToCAndLLVMFnptr-28         18215420                66.29 ns/op

可以看出:

  • 采用Funcptr和直接内联调用的性能是一样的
  • 在C中分配内存要比使用Go传递内存快一些
  • llvm是setmem相对于直接在go中set met还是要快一些,但是还是没有直接调用c函数set met来的更快

References

Documentation

The Go Gopher

There is no documentation for this package.