← Back to context

Comment by ashvardanian

2 days ago

The GoLang bindings – yes, they are based on cGo. I realize it's suboptimal, but seems like the only practical option at this point.

In a normal world the Go C FFI wouldn't have insane overhead but what can we do, the language is perfect and it will stay that way until morale improves.

Thanks for the work you do

  • There are undoubtedly still some optimizations lying around, but the biggest source of Go's FFI overhead is goroutines.

    There's only two "easy" solutions I can see: switch to N:N threading model or make the C code goroutine-aware. The former would speed up C calls at the expense of slowing down lots of ordinary Go code. Personally, I can still see some scenarios where that's beneficial, but it's pretty niche. The latter would greatly complicate the use of cgo, and defeat one of its core purposes, namely having access to large hard-to-translate C codebases without requiring extensive modifications of them.

    A lot of people compare Go's FFI overhead to that of other natively compiled languages, like Zig or Rust, or to managed runtime languages like Java (JVM) or C# (.NET), but those alternatives don't use green threads (the general concept behind goroutines) as extensively. If you really want to compare apples-to-apples, you should compare against Erlang (BEAM). As far as I can tell, Erlang NIFs [1] are broadly similar to purego [2] calls, and their runtime performance [3] has more or less the same issues as CGo [4].

    [1]: https://www.erlang.org/doc/system/nif.html

    [2]: https://pkg.go.dev/github.com/ebitengine/purego

    [3]: https://erlang.org/documentation/doc-10.1/doc/efficiency_gui...

    [4]: https://www.reddit.com/r/golang/comments/12nt2le/when_dealin...

  • In a real (not "normal") world, trade-offs exist and Go choose a specific set of design points that are consequential.