← Back to context

Comment by akkad33

3 months ago

Is calling Rust from Go fast? Last time I checked the interface between C and Go is very slow

No, it is not all that fast after the CGo call marshaling (Rust would need to compile to the C ABI). I would essentially call in to Rust to start the code, run it in its own thread pool and then call into Rust again to stop it. The time to start and stop don't really matter as this is code that runs from minutes to hours and is embarrassingly parallel.

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