v1.2.1
wazero 1.2.1 is an easy upgrade decision for everyone: There is no public API change of any kind, yet updating gives you a more portable and faster wasm runtime.
This release was helped and motivated by friendly projects in our ecosystem, please star their repos!
- go needs non-blocking I/O for the new
GOOS=wasip1
, for example, running an HTTP server with middleware, using only one thread. - go-sqlite3 wants smaller and faster machine code to make queries more performant.
- wasi-go collaborated on a different approach to non-blocking I/O.
As usual, we have a hefty amount of background for you to enjoy, even if you aren't a wazero user, yet. Please star our repo if you like it!
Progress in non-blocking I/O
WebAssembly does not yet support true parallelism; it lacks support for multiple threads, atomics, and memory barriers. This may be addressed portably in the future, when the threads proposal standardizes and common concerns like garbage collection employ it. For now, the only way to safely use wasm is sequentially, like how GOMAXPROCS=1
works in Go.
This isn't a problem in a lot of cases, but in I/O it can be. Network services often need to accept new connections while processing existing ones. Interleaving of this isn't viable with blocking I/O. The typical way to address this is using non-blocking I/O, with a loop that looks for channels which are ready and processes accordingly.
As mentioned in the 1.2.0 release, non-blocking I/O is a work in progress, and it is improved in 1.2.1. This is improved so much that @chriso was able to remove skips for HTTP and file-based non-blocking tests in the emerging GOOS=wasip1
in Go 1.21.
@evacchi focused on the problem of non-blocking I/O, both network sockets and files. He both invented some solutions and leveraged existing approaches from wasi-go to fix issues such as inability to use HTTP middleware in Go source compiled to wasm. To make sure it worked, he landed new tests, for example C code compiled with wasi-libc and go(tip) compiled with GOOS=wasip1
.
The changes are all transparent to end users, and while Edo led this effort, @achille-roussel and @chriso deserve a large thank you for support and the some prior art in wasi-go.
One final note is the battle is not over. We still have work to do in windows and surely there will be more edge cases. Please track issue 1500 and add comments if you noticed any more glitches.
Significant execution time savings
While developing go-sqlite3, @ncruces noticed some opportunities both to save size in machine code and performance. This focused on "traps" which are unresolvable execution errors that happen in cases such as divide by zero or invalid bounds conditions. The basic idea was to centralize the concern, so that any instruction that could trap uses the same way out of machine code.
While developing this, Nuno found a glitch which is fast-pathing these cases can interfere with source code mapping. For example, if you were using a debugger or using a DWARF-enabled trace, the line numbers could be wrong. After discussing with others, a pragmatic way out was chosen: optimize when there is either no debug information (usually the case in release builds) or if RuntimeConfiguration.WithDebugInfoEnabled
is set to false. The latter is helpful, because it can be difficult to prevent a compiler from obfuscating function names, so some may use debug builds always. This is handy in the case of a rare bug such as a nil pointer, because you can still identify original source function by name.
While led by @ncruces, others were involved in review and design. This was made easier because Nuno kept excellent notes and comments, as well made speedtest1 to test results. @achille-roussel and @mathetake contributed feedback and @evacchi ported the implementation over to arm64 a lot easier due to the rigor involved.
The end results are really quite excellent, especially as debug info is rarely used in release builds. For example, an unrelated project kube-scheduler-wasm-extension performance improved with real data, up to 6.5%, with no other changes except upgrading to the latest patch.
Note on TinyGo v0.28.1
We updated our TinyGo examples to v0.28.1, which supports more features (such as ReadDir and json), and more idiomatic wasm import signatures. A lot went into this release, so please thank the TinyGo team with a star!
- //go:wasm-module env
- //export log
+ //go:wasmimport env log
func _log(ptr, size uint32)