In a project I'm working on I need to use a bunch of C functions from Go. The current implementation is using cgo to achieve that, but doing so has a massive performance impact, which I am trying to remove.
- cgo marks all C code as a syscall, causing the scheduler to allocate a new thread if needed. Since ~80% of the CPU time in my project is spent doing the heavy C work, this quickly results in having a lot of threads (500+ instead of
GOMAXPROCS
(= 8)), which my Linux kernel does not like much. - Doing the usual 'limiter' approach (have a buffered channel lock the cgo calls) results in a lot of mutexes, slowing the program down.
I want to keep using Go for this project as it's a great way of managing concurrency.
Things I have tried :
- Comment out some stuff like
entersyscall()
insrc/runtime/cgocall.go
(didn't seem to help much, and I'd prefer to avoid modifying the Go code). - Put my code in a .c file and call it from Go, without the
import "C"
. No luck here - I couldn't call the function and when I wrote the function names aspackage·function
the compiler complained about invalid characters in the file. - Use a .s file and just write it as assembly. My asm isn't that great and I couldn't figure it out.
So, my question is: how does one use C functions from Go while avoiding the overhead of cgo?
Side note: I'm aware of why cgo marks all calls as a syscall, but in this specific case the functions I call do not block on locks or IO.