A few years back we tried moving our in-memory database engine from Typescript to Rust but found the prototype gains were pretty much deleted by wasm-bindgen because of the high call frequency in our setting.
Moving more of our stack into Rust wasn't viable, so we shelved the project and focused on other areas.
Turns out this is a pretty common experience.
Now we're trying again, but this time with our own binding protocol. It’s 2.5× faster at the boundary, but more importantly, it shifts the break-even point dramatically. Offloading to WASM becomes viable at much smaller data sizes (e.g. ~100 elements), enabling cases that weren’t previously worth it — including ours.
The only trade off is significantly worse DX - the bindings are manual and more verbose, but I'm sure someone could solve this with codegen/macros on either side. For now we're focused on performance.
It's pretty much neck and neck between our Rust and Zig implementations so take your pick.
InkCanon•1h ago
Could you explain more on what bindgen was lacking and what you did different?
tristanhoy•59m ago
wasm-bindgen generates a lot of marshalling code on both sides with dynamic allocations and this kills performance.
tristanhoy•2h ago
Moving more of our stack into Rust wasn't viable, so we shelved the project and focused on other areas.
Turns out this is a pretty common experience.
Now we're trying again, but this time with our own binding protocol. It’s 2.5× faster at the boundary, but more importantly, it shifts the break-even point dramatically. Offloading to WASM becomes viable at much smaller data sizes (e.g. ~100 elements), enabling cases that weren’t previously worth it — including ours.
The only trade off is significantly worse DX - the bindings are manual and more verbose, but I'm sure someone could solve this with codegen/macros on either side. For now we're focused on performance.
It's pretty much neck and neck between our Rust and Zig implementations so take your pick.
InkCanon•1h ago
tristanhoy•59m ago
For low-level algorithms, this means that JS + wasm-bindgen will only be marginally faster than pure JS - the overhead of crossing the boundary is that much of an issue: https://dev.to/bence_rcz_fe471c168707c1/rust-webassembly-per...
With zaw, it uses a pre-allocated, fixed-width buffer for communication, same technique as Bence uses in that article.
It's a night and day difference.