-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
runtime: _cgoCheckPointer0 extreme overhead #14265
Comments
Thanks for the test case. I don't know how to do much better for this kind of example. The pointer passing rules say that if you pass the address of an element of a slice, the C code is permitted to examine every element of the slice. You are passing the address of a 1000000 slice of pointers, so each call needs to check 1000000 pointers to make sure that they are not Go pointers. |
Thanks Ian for the clear description! Now I think I understand another strange thing: with Back to the original issue: this understanding allows a not-too-ugly workaround:
By calling with a one-element-length array (capped), it works:
Here the "Naive" is the old version, the "Sliced" is the carr := arr[i:i+1] version, and the "Capped" is the above carr := arr[i:i+1:i+1] version. (same repo has the new code). I think at least we should document it more explicitly, that the cgo checker checks all reachable pointers in the struct/array/slice level. |
Go 1.6 has a strict checker to disable passing memory allocated by Go that contains Go pointers ("Go pointer to Go pointer"). So we have to C.malloc everywhere where we want C to write to memory, and read it in Go. See https://tip.golang.org/cmd/cgo/#hdr-Go_references_to_C for the documentation, https://tip.golang.org/pkg/unsafe/ for the slice tricks, and https://groups.google.com/forum/#!topic/golang-nuts/gnH0nhPf36I for the hunt. Put some cgo helper function in bnd_hlp.go, and some C for cycles in version.c. Extra care needed when passing pointers of array/slice elements with cgo: use the whole array on C side, or move the for cycle to C side. See golang/go#14265 for details of the cgo check overhead.
go1.6rc2
linux/amd64
Call C code with cgo.
Almost the same performance with GODEBUG=cgocheck=1 and GODEBUG=cgocheck=0.
22 times more running time with GODEBUG=cgocheck=1 than with GODEBUG=cgocheck=0.
The overhead is 22x in practice and 36000 in this contrived example:
$ GODEBUG=cgocheck=1 go test -bench=. -run=-
testing: warning: no tests to run
PASS
BenchmarkCGO-4 50 28792524 ns/op
ok github.com/tgulacsi/go/cgo22 1.855s
:gthomas@waterhouse: ~/src/github.com/tgulacsi/go/cgo22
$ GODEBUG=cgocheck=0 go test -bench=. -run=-
testing: warning: no tests to run
PASS
BenchmarkCGO-4 2000000 796 ns/op
ok github.com/tgulacsi/go/cgo22 2.988s
:gthomas@waterhouse: ~/src/github.com/tgulacsi/go/cgo22
The code is at https://github.com/tgulacsi/go/tree/master/cgo22
cgo22.zip
The text was updated successfully, but these errors were encountered: