Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
runtime: _cgoCheckPointer0 extreme overhead #14265
The overhead is 22x in practice and 36000 in this contrived example:
$ GODEBUG=cgocheck=1 go test -bench=. -run=-
The code is at https://github.com/tgulacsi/go/tree/master/cgo22
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.