Skip to content

wazero v1.0.0-pre.4

Pre-release
Pre-release
Compare
Choose a tag to compare
@codefromthecrypt codefromthecrypt released this 02 Dec 03:11
· 1196 commits to main since this release
b4f3371

wazero v1.0.0-pre.4 focuses on portability, and ultimately led to a couple notable new projects using wazero: mosn and pdfium-cli. We also improved performance and infrastructure needed to develop faster. While we have a lot more to go, this version is significantly better and worth looking at and upgrading. Please star repositories of those who help keep this project working!

We want to recognize a couple end users whose direct efforts made wazero better for everyone. They are without a doubt the MVPs of v1.0.0-pre.4

@ckaznocha began the month optimizing how we instantiate modules, so that they are fast enough for request-scope. Clifton used a scientific approach, showing other people how to do flame graphs to see for themselves the performance before and after. The results were verifiable by benchmarks and also ad-hoc feedback from others in the community. Just fantastic work and a good role model.

@jerbob92 worked very hard to migrate a project which used CGO to wasm for access to PDFium. The end result was a statically compiled Go binary which embeds PDFium compiled to a wasm binary. This solved the install problem as there's no longer a shared library dependency. We are thankful to Jeroen for tens of hours of skilled, dedicated time: he worked night and day not just to fix problems he needed, but also do those in a way others can understand and consume them. This dramatically improved wazero's support of emscripten and WASI, as well meaningful clarifications on both API and processes to improve them. Please reach out and thank @jerbob92 if this benefits you!

Now, let's get to the concrete changes in wazero v1.0.0-pre.4

Much improved WASI

Thanks to @jerbob92, we have more WASI functions implemented than before, notably filesystem in nature: fd_filestat_get, fd_pread and fd_readdir. This means you can implement a command like ls in wasm and wazero can execute it.

We have better infrastructure to develop WASI functionality. This is helpful because often specifications only have a sentence or two description on the behavior one is to implement. We decided that the most effective way to address the gap is testing at least two real compilers before assuming our implementation is correct. Our first test was implementing ls in a couple compilers and making sure that must pass on every change.

https://github.com/tetratelabs/wazero/blob/v1.0.0-pre.4/imports/wasi_snapshot_preview1/wasi_stdlib_test.go

Build compatibility is now one version behind Go's support policy

Before, we supported exactly the same version policy as Go: latest and one before. As of this release it would mean Go 1.19 and 1.18. We had feedback from mosn that this policy is too aggressive as it isn't viable for users to switch so quickly. In surveying, we found a more common approach is one version behind, so three total versions. We decided to go with this, as it still allows us to use Go 1.18 features when we release 1.0 early next year.

Better host function debugging

Before, we had function listeners, but they only worked in the interpreter engine. Most people auto-select the fastest engine, which is the compiler. This meant more config work to use things like function listeners. Thanks to @mathetake, now anyone can use function listeners (noting this is an experimental API).

For example, the below will show you which WASI calls your code uses, to STDOUT:

// Set context to one that has an experimental listener
ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewHostLoggingListenerFactory(os.Stdout))

r := wazero.NewRuntime(ctx)
defer r.Close(ctx) // This closes everything this Runtime created.
...

api.GoModuleFunc now accepts a stack parameter

Few users will define host functions using the low-level api.GoModuleFunc API as it is more tricky. We changed the api slightly to allow it to allocate less, which helps performance of built-in functions and advanced third party functions.

 type GoModuleFunction interface {
-       Call(ctx context.Context, mod Module, params []uint64) []uint64
+       Call(ctx context.Context, mod Module, stack []uint64)
 }

Most users will need to do nothing as all code that used this API on GitHub have been updated.

Significant performance optimizations and infrastructure improvements

@ckaznocha made numerous optimizations to reduce cost to initialize a module. These help for users who compile once, but want a fresh module per-request. This is the safest way to execute webassembly functions quickly as it prevents side-effects between calls. @mathetake made numerous compiler improvements and added fuzzing to the default PR checks. He also ensured wazero passes on the latest version of WebAssembly 2.0 spec tests. @anuraaga found a corruption issue we corrected when people cache results, which is now fixed. @robbertvanginkel fixed a reference counting bug affecting users of gojs (which runs wasm built by GOOS=js GOARCH=wasm go build ...)

Other notable changes

  • @codefromthecrypt added wasi_snapshot_preview1.NewFunctionExporter to allow changing the WASI module name (e.g. to "wasi_unstable") or overriding built-in functions.
  • @jerbob92 and @codefromthecrypt added built-in invoke_xxx functions for Emscripten. Future change will generate these on demand given a wasm binary.
  • @mathetake added encode and encode functions for int32 and uint32 to help clarify that api.Function result arrays are intended to be decoded. Thanks to @jerbob92 for elaboration