Comment by spiffyk
3 months ago
I have no experience with FFI between C and Go, could anyone shed some light on this? They are both natively compiled languages – why would calls between them be much slower than any old function call?
3 months ago
I have no experience with FFI between C and Go, could anyone shed some light on this? They are both natively compiled languages – why would calls between them be much slower than any old function call?
There are two reasons:
• Go uses its own custom ABI and resizeable stacks, so there's some overhead to switching where the "Go context" must be saved and some things locked.
• Go's goroutines are a kind of preemptive green thread where multiple goroutines share the same OS thread. When calling C, the goroutine scheduler must jump through some hoops to ensure that this caller doesn't stall other goroutines on the same thread.
Calling C code from Go used to be slow, but over the last 10 years much of this overhead has been eliminated. In Go 1.21 (which came with major optimizations), a C call was down to about 40ns [1]. There are now some annotations you can use to further help speed up C calls.
[1] https://shane.ai/posts/cgo-performance-in-go1.21/
And P/Invoke call can be as cheap as a direct C call, at 1-4ns
In Unity, Mono and/or IL2CPP's interop mechanism also ends up in the ballpark of direct call cost.
There's some type translation and the Go runtime needs to turn some things off before calling out to C