Skip to content

v1.2.0

Compare
Choose a tag to compare
@github-actions github-actions released this 03 Jun 07:49
· 691 commits to main since this release
97d0d70

wazero 1.2.0 includes 33 days of valiant effort towards performance, interop and debug goals, shared not only in wazero, but WebAssembly in general. We appreciate folks waiting a couple more days than usual and expect you'll enjoy what you see below.

While we haven't set a formal post 1.0 release cadence, you can expect another patch or minor within a month. Meanwhile, this is our most performant and best tested release yet. As always, star all the projects that interest you, and say thanks when you can.

Performance

Performance is something we aim to always improve, release to release. This includes looking at memory usage as well as latency. While there were multiple people involved in efficiency work, @achille-roussel and @lburgazzoli deserve special call outs for leading efforts, and @ncruces deserves a big pat on the back for contributing reviews, cleanups and advice.

@achille-roussel made many changes internal to our compiler, as well linux-only specializations such as using huge pages for the memory mapped regions under wasm functions. These were all profile and benchmark guided changes and proposed in top rigor.

@lburgazzoli tracked down best practice in TinyGo, consolidating advice from various experts, such as the primary developer of TinyGo @aykevl. He worked with @ncruces to make sure our allocation example is not just a code snippet, but an exemplar of good practice, without risk of memory leaks and performance validated with benchmarks.

The combination of backend work (e.g. runtime improvements) and frontend work (e.g. changes to our TinyGo example) combined in a notable holistic gain across the board. This was true teamwork and a job well done!

$ benchstat v1.1.0.txt v1.2.0.txt 
goos: darwin
goarch: arm64
pkg: github.com/tetratelabs/wazero/internal/integration_test/vs/compiler
                          │  v1.1.0.txt  │             v1.2.0.txt             │
                          │    sec/op    │   sec/op     vs base               │
Allocation/Compile-12       3.365m ±  1%   3.174m ± 1%   -5.66% (p=0.002 n=6)
Allocation/Instantiate-12   149.1µ ± 26%   120.4µ ± 7%  -19.23% (p=0.002 n=6)
Allocation/Call-12          1.404µ ±  2%   1.297µ ± 2%   -7.66% (p=0.002 n=6)
geomean                     88.97µ         79.13µ       -11.05%

                          │  v1.1.0.txt  │              v1.2.0.txt               │
                          │     B/op     │     B/op      vs base                 │
Allocation/Compile-12       2.404Mi ± 0%   1.292Mi ± 0%  -46.24% (p=0.002 n=6)
Allocation/Instantiate-12   319.4Ki ± 0%   230.5Ki ± 0%  -27.84% (p=0.002 n=6)
Allocation/Call-12            48.00 ± 0%     48.00 ± 0%        ~ (p=1.000 n=6) ¹
geomean                     33.28Ki        24.27Ki       -27.07%
¹ all samples are equal

                          │ v1.1.0.txt  │              v1.2.0.txt              │
                          │  allocs/op  │  allocs/op   vs base                 │
Allocation/Compile-12       1.830k ± 0%   1.595k ± 0%  -12.84% (p=0.002 n=6)
Allocation/Instantiate-12    803.0 ± 0%    508.0 ± 0%  -36.74% (p=0.002 n=6)
Allocation/Call-12           5.000 ± 0%    5.000 ± 0%        ~ (p=1.000 n=6) ¹
geomean                      194.4         159.4       -18.00%
¹ all samples are equal

Interop

Compatibility is a moving target as both specifications change as well understanding of specifications. For example, the WebAssembly Core Specification 2.0 remains in a draft state, and expectations of the VM change as it changes. Also the d'facto WASI version preview1 (a.k.a. wasip1) had no tests, nor detailed documentation for the first several years of its existence. This left interop as more a quorum of implementation practice vs a spec. While new initiatives such as the wasi-testsuite and wasix aim to stabilize this, WASI compatibility remains a source of work from wazero maintainers and compiler developers. We really appreciate the efforts spent here to keep as many users unaware of these glitches as possible.

On the WebAssembly Core (VM) side, we appreciate @mathetake updating our code and spec suite to pass latest changes there. Also, we appreciate an attempt by @anuraaga with support by @ncruces on the Threads proposal, despite us ending up parking the idea until the proposal finishes.

On the WASI side, we appreciate a lot of work driven by the team working on Go. Specifically, the upcoming GOOS=wasip1 planned for 1.21 helped reveal a number of grey areas that required work to support in Go without breaking other languages. Championing these came from various team members including @Pryz, @achille-roussel and @evacchi on various file rights and non-blocking related glitches, some fixing other language runtimes such as python.

We're also excited that @evacchi began an experiment to support sockets, currently working for blocking requests. As wasm only has one thread to use, libraries often need non-blocking functionality to do anything notable. We'll report more on sockets once non-blocking glitches sort out.

Meanwhile, those using sockets know that the preview1 version of WASI is extremely limited. There are other ABI such as wasmedge_wasi_socket, wasi-sockets and most recently wasix. All of these go beyond the simple TCP sock accept, read/write in wasip1. If you'd like the bleeding edge socket support, please try wasi-go and request the features you want to experiment with. This project is a layer over wazero with an alternate syscall layer. wasi-go can move faster due to less constraints than upstream, such as Windows or virtual files. This makes it a lower risk and ideal playground to develop evolving host function (ABI) specifications. As these functions mature, what makes sense to build-in will land upstream in wazero.

Debug

We are very excited to power the only known out-of-browser CPU and memory profiler for WebAssembly, wzprof. wzprof brings the power of pprof to wasm, regardless of if the source language is Go or not.

wzprof has already served a lot of benefits in its short life so far. For example, the kube-scheduler-wasm-extension used it to isolate a garbage collection problem endemic in large protobuf decoders compiled to wasm.

Implementing this required significant work in wazero, which we are happy went upstream! @pelletier added the source offset to experimental.StackIterator which allows source-mapping in debugging use cases. @achille-roussel polished the experimental.FunctionListener to be more performant, including optimizing its API around errors and removing context propagation. @chriso and @mathetake helped fix some glitches along the way. Finally, @achille-roussel made it easier to develop 3rd party listeners by adding experimental.FunctionListenerFactory to supply them and wazerotest.Module to test them.

While we don't expect a lot of people to implement listeners, it was a great team effort to get the substrate together to the point you can build a profiler on top of it. Kudos especially to the wzprof team on finally giving wasm developers a decent profiler!

What's next?

In the short term, we'll try to close the gaps on non-blocking I/O inside WASI. We still aim to have a fully pluggable filesystem soon, including an in-memory option for those needing to provide something like tmpfs from Go. Of course compatibility issues and user demands will take priority as they always do.

Longer term, @mathetake is taking on the task of an optimizing compiler affectionately named wazevo. This will likely take a year to mature, and will narrow the performance gap on certain libraries like libsodium without adding any platform dependencies whatsoever.

Meanwhile, if you want updates you can always contact the community and ask, or just wait for the next release. Until next time!