We're using it at RunReveal and I've got to say that we're extremely happy with it.
At Segment I always wanted a good sandbox environment for running customer code. This is the ideal solution, and the fact that it doesn't require CGo: :chefs_kiss:
Happy to answer any questions people considering using it might have!
Using WASM for things requiring low IO and high compute that are traditionally written in C/C++ makes a lot of sense to me. Image codecs are an example and native implementations for things like JPEG encoders are hard to come by. So, I used wazero to implement a few image codecs in Go^1. Codecs were compiled to WASM, and wazero works great for running them (albeit with overhead).
For this use case, wazero appears to be the cleanest solution as it's the only runtime that doesn't need CGo. The biggest appeal to me embedding WASM in Go is avoiding CGo to allow cross compilation. If my dependency is using CGo anyway, I might as well as link against a C library. I think native WASM runtimes like wazero are currently the best options for porting code language-agnostically.
I've used wazero for a pet project (raw wasm generation from simple query plans) and it was really nice to work with!
I also had to play around a bit with wasm relocations and the encoding/decoding libraries they've built are very readable, too, so I was able to hack together what I needed.
Fingers crossed for the optimizing compiler that's planned for some point!
what are you using for generating wasm? tinygo or new go runtime support of wasm? what are the sizes of wasm binaries? last i checked helloworld was in the order of few MB's.
The project was a custom compiler to turn a simple query plan (think select, where, group by) into wasm. So it was basically hand-written raw wasm generation.
I did compile some helper functions from Rust though, which also served as the "skeleton" of the wasm artifact I was later generating my wasm into, since wasm doesn't have any kind of proper dynamic linking right now.
tinygo still wins for size, and the reflection story got better (json works!). The traditional Go compiler produces larger binary but OTOH it's super-fast, as fast as native builds!
Can someone explain this to me like I’m 5? I thought web assembly was primarily run in a browser. Is this saying you can run a wasm binary in your go project (outside of the browser)?
That is correct. It is a webassembly runtime that you can embed in your go project. There are also other wasm runtimes that run outside the browser, this is one written in Go
Haven't looked at it, but I assume the use-case is opposite of your suggestion, i.e. CUE wants to offer some kind of plugin integration and embedding a WASM runtime is the safest way.
as far as I know wazero is the only zero-dependency Wasm runtime written in Go.
This is not just one of those "written in $LANG" kinda deal: most other runtimes require linking against a native library; this in turn plays against a lot of the killer features of Go, such as good tooling, easy cross-compilation, goroutines [0]; so, not requiring Cgo means a team may bring wazero to their Go project without a second thought.
As for other features, we may not be as bleeding edge as other projects, but we are a rather tiny team. If you expect support for WASI (preview 1) we have it :) we try to concentrate our effort on high-quality support of stable specs.
EDIT: oh, and a huge shout-out to Stealthrocket, they are building a lot of cool stuff on top of wazero:
I'm one of the Dapr (Distributed Application Runtime) maintainers which has a wazero based wasm integration. The wazero team contributed this integration.
I just wanted to say that the wazero team has done a great job keeping the integration up to date and have been very responsive. For example, our project also supports Linux Arm32 and wazero was initially not testing against that architecture which led to a compile issue for us. Once we pointed this out they fixed this and added this architecture to their CI tests as well.
EDIT: Also because our project can be compiled for any common O/S and architecture combination the pure Go implementation is critical. We do not accept use of CGO.
It depends on what you mean for JIT. wazero is load-time AoT; i.e. we compile the module in-memory on load, for efficient execution later, when you instantiate, it is not AoT in the sense that we produce a stand-alone executable, the runtime is always hosting that executable code that is generated, and we go back-and-forth between translated wasm and "Go space" at run-time in many cases. It is AoT in the sense that we do not tune the generated code depending on tracing or profiling information, because we don't track it for compilation.
The Wasm model itself gives a certain degree of safety: e.g. you do not have complete control over the host OS, because you have to explicitly expose functions to the gues module; we also provide a certain degree of control over e.g. execution time (you can instantiate a module in such a way that executions can be cancelled or set a timeout) and memory space.
We also provide an interpreter for all platforms where Go runs, and Takeshi (the founder of the project) is also working on bootstrapping an optimizing compiler that should soon land on main, and more work will happen in that space.
wasmtime and wasmer are basically state-of-the-art. Our compilation backend is a fast, but straightforward translator from wasm to binary (think v8 liftoff vs turbofan), so it's faster than interpreting, but still slower than a well-crafted optimizing compiler. However depending on your use case, that kind of performance may not be everything: e.g. when I/O dominates .
The good news is an optimizing backend is being worked on as we speak and should be available very soon :)
Any plans to support the WebAssembly GC proposal? Binaryen supports GC structs and arrays now, but there aren’t a lot of runtimes that have it yet. It would be cool if Wazero could do it in a way where managed structs can be seamlessly shared across the Wasm/Go boundary using the native Go GC.
We are tracking the evolution of most proposals but we are a tiny team so we try to concentrate our efforts on those that have a higher degree of maturity, but I am sure we will at some point :)
At Segment I always wanted a good sandbox environment for running customer code. This is the ideal solution, and the fact that it doesn't require CGo: :chefs_kiss:
Happy to answer any questions people considering using it might have!
For this use case, wazero appears to be the cleanest solution as it's the only runtime that doesn't need CGo. The biggest appeal to me embedding WASM in Go is avoiding CGo to allow cross compilation. If my dependency is using CGo anyway, I might as well as link against a C library. I think native WASM runtimes like wazero are currently the best options for porting code language-agnostically.
^1: https://github.com/yklcs/wasmimg
I also had to play around a bit with wasm relocations and the encoding/decoding libraries they've built are very readable, too, so I was able to hack together what I needed.
Fingers crossed for the optimizing compiler that's planned for some point!
I did compile some helper functions from Rust though, which also served as the "skeleton" of the wasm artifact I was later generating my wasm into, since wasm doesn't have any kind of proper dynamic linking right now.
Just like JavaScript was made to run in a browser, but additional runtimes have been created.
https://github.com/cue-lang/cue/blob/0520a3f9e73e63d77e43c9b...
You can already do CUE via WASM, this is how the playground works.
https://cuelang.org/play/?id=#cue@export@cue
This is not just one of those "written in $LANG" kinda deal: most other runtimes require linking against a native library; this in turn plays against a lot of the killer features of Go, such as good tooling, easy cross-compilation, goroutines [0]; so, not requiring Cgo means a team may bring wazero to their Go project without a second thought.
As for other features, we may not be as bleeding edge as other projects, but we are a rather tiny team. If you expect support for WASI (preview 1) we have it :) we try to concentrate our effort on high-quality support of stable specs.
EDIT: oh, and a huge shout-out to Stealthrocket, they are building a lot of cool stuff on top of wazero:
- wzprof, a wasm profiler integrating with pprof https://github.com/stealthrocket/wzprof
- timecraft, a wasm time-traveling runtime https://github.com/stealthrocket/timecraft
[0] see "CGO is not Go" https://dave.cheney.net/2016/01/18/cgo-is-not-go
I just wanted to say that the wazero team has done a great job keeping the integration up to date and have been very responsive. For example, our project also supports Linux Arm32 and wazero was initially not testing against that architecture which led to a compile issue for us. Once we pointed this out they fixed this and added this architecture to their CI tests as well.
EDIT: Also because our project can be compiled for any common O/S and architecture combination the pure Go implementation is critical. We do not accept use of CGO.
The Wasm model itself gives a certain degree of safety: e.g. you do not have complete control over the host OS, because you have to explicitly expose functions to the gues module; we also provide a certain degree of control over e.g. execution time (you can instantiate a module in such a way that executions can be cancelled or set a timeout) and memory space.
We also provide an interpreter for all platforms where Go runs, and Takeshi (the founder of the project) is also working on bootstrapping an optimizing compiler that should soon land on main, and more work will happen in that space.
The good news is an optimizing backend is being worked on as we speak and should be available very soon :)