Hacker News new | past | comments | ask | show | jobs | submit login
Calling Rust from Cursed Go (pthorpe92.dev)
33 points by dvektor 14 hours ago | hide | past | favorite | 8 comments





Thank you author for your kind words about my Go SQLite driver.

That said, purego solves a build infrastructure issue, not a perfomance issue. You're still using the same underlying mechanisms to call into C, and the same performance is expected. I'm not the one saying this, read the authors: https://github.com/ebitengine/purego/issues/202

wazero uses a different mechanism, the one used to call Go assembly, but adds its own overhead (trampolines, adapting calling conventions, and the inherent Wasm sandbox overhead, e.g. the guest can't read the host's memory, there's bounds checks, etc).

Also “Cgo is fast” and “Cgo is slow” is not the correct framing; rather it depends, for various reasons:

- Cgo is a moving target (it mostly improves with time, but can regress)

- it's different to just call C from Go, or then callback Go from C

- there's not just call overhead to consider, but also scheduler overhead which is much harder to measure consistently


You are welcome sir, I quite enjoyed digging into your implementation a bit. I have been absorbing as much as I can to better understand sqlite and its general ecosystem.

Yup you are absolutely right. My thought was that my next post would dive into exploring whether or not this actually solved any of the issues listed about CGO. I updated the post to be a little more clear.


> For performance, Go using CGO is going to be closer to Python than Go.

That has not been my experience at all. While there’s still some overhead, recent versions have cgo per-call overhead under 50ns. Python is still nowhere near close especially with multiple threads being used.


Indeed until the Python community embraces state of the art JIT compilers on the reference implementation, this is definitely not the case.

Yes, even with PyPy's heroic efforts.


> For performance, Go using CGO is going to be closer to Python than Go.

This is not true. In a lot of libraries, unless there are asm implementations on the pure Go side, the CGO implementation often outperforms. Zstd used to be one of the most notable example.

> CGO is slow and often still painful to build cross platform.

This is true. I found that using Bazel to manage the entire build graph made CGO a lot easier to deal with. By adopting Bazel, you formalize the cost of operating a cc toolchain and sysroot up front instead of hiding it inside nested layers of environment variables and CI container images. Bazel also made your build faster and cross-platform CGO easier.

> Go is no longer able to be built into a single static binary.

The "C" portion of CGO can be made static as well. It often results in a much bigger binary than a dynamically-linked binary though. In setups where you control the runtime environment (i.e. web servers), I don't see a clear benefit in shipping duplicate bytes inside a static binary. Even for consumer-facing use cases (i.e. devtools), a static binary can be too big and unwieldy versus just a set of pre-built binaries targeting specific platforms via Github Release.


Worth reading: https://www.yuchanns.xyz/posts/bridging-rust-and-native-go/

The Apache OpenDAL community is using PureGo and libffi to create Go bindings for OpenDAL.


> Go is no longer able to be built into a single static binary.

Neither does Rust technically, as it depends on the platform OS APIs, which outside embedded OSes, are only available as dynamic libraries on modern OSes.


> Go is no longer able to be built into a single static binary

In Linux, I had quite good successes building in Alpine under MUSL. Real static binaries.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: