Collects README links at the bottom (#515)

Collecting README links at the bottom helps with formatting. I made
some editorial changes, notably pointing people at the WebAssembly 2.0
issue which I'm fleshing out separately.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2022-04-30 12:18:58 +08:00
committed by GitHub
parent 2c03098dba
commit abd1c79f33
3 changed files with 128 additions and 140 deletions

233
README.md
View File

@@ -4,15 +4,17 @@ WebAssembly is a way to safely run code compiled in other languages. Runtimes
execute WebAssembly Modules (Wasm), which are most often binaries with a `.wasm`
extension.
wazero is a [WebAssembly 1.0 (20191205)](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/) spec compliant runtime written in Go.
It has *zero dependencies*, and doesn't rely on CGO. This means you can
run applications in other languages and still keep cross compilation.
wazero is a [WebAssembly 1.0][1] spec compliant runtime written in Go. It has
*zero dependencies*, and doesn't rely on CGO. This means you can run
applications in other languages and still keep cross compilation.
Import wazero and extend your Go application with code written in any language!
## Example
The best way to learn this and other features you get with wazero is by trying one of our [examples](examples).
The best way to learn this and other features you get with wazero is by trying
one of our [examples](examples).
For the impatient, here's how invoking a factorial function looks in wazero:
```golang
@@ -22,7 +24,7 @@ func main() {
// Read a WebAssembly binary containing an exported "fac" function.
// * Ex. (func (export "fac") (param i64) (result i64) ...
source, _ := os.ReadFile("./tests/bench/testdata/fac.wasm")
source, _ := os.ReadFile("./path/to/fac.wasm")
// Instantiate the module and return its exported functions
module, _ := wazero.NewRuntime().InstantiateModuleFromCode(ctx, source)
@@ -33,9 +35,9 @@ func main() {
}
```
Note: While the [source for this](internal/integration_test/bench/testdata/fac.wat) is in the
WebAssembly 1.0 (20191205) Text Format, it could have been written in another
language that compiles to (targets) WebAssembly, such as AssemblyScript, C, C++, Rust, TinyGo or Zig.
Note: `fac.wasm` was compiled from [fac.wat][3], in the [WebAssembly 1.0][1]
Text Format, it could have been written in another language that compiles to
(targets) WebAssembly, such as AssemblyScript, C, C++, Rust, TinyGo or Zig.
## Deeper dive
@@ -66,11 +68,11 @@ if err != nil {
defer env.Close(ctx)
```
While not a standards body like W3C, there is another dominant community in the
WebAssembly ecosystem: [The Bytecode Alliance](https://github.com/bytecodealliance/governance).
The Bytecode Alliance controls the WebAssembly System Interface ([WASI](https://github.com/WebAssembly/WASI)),
which is a set of function imports similar to Go's [x/sys/unix](https://pkg.go.dev/golang.org/x/sys/unix).
The "wasi_snapshot_preview1" version of WASI is widely implemented, so wazero
The WebAssembly community has [subgroups][4] which maintain work that may not
result in a Web Standard. One such group is the WebAssembly System Interface
([WASI][5]), which defines functions similar to Go's [x/sys/unix][6].
The [wasi_snapshot_preview1][13] tag of WASI is widely implemented, so wazero
bundles an implementation. That way, you don't have to write these functions.
For example, here's how you can allow WebAssembly modules to read
@@ -91,42 +93,59 @@ they may answer them for you!
## Runtime
There are two runtime configurations supported in wazero, where _JIT_ is default:
1. _Interpreter_: a naive interpreter-based implementation of Wasm virtual machine. Its implementation doesn't have any platform (GOARCH, GOOS) specific code, therefore _interpreter_ can be used for any compilation target available for Go (such as `riscv64`).
2. _JIT_: compiles WebAssembly modules, generates the machine code, and executing it all at runtime. Currently wazero implements the JIT compiler for `amd64` and `arm64` target. Generally speaking, _JIT_ is faster than _Interpreter_ by order of magnitude. However, the implementation is immature and has a bunch of aspects that could be improved (for example, it just does a singlepass compilation and doesn't do any optimizations, etc.). Please refer to [internal/wasm/jit/RATIONALE.md](internal/wasm/jit/RATIONALE.md) for the design choices and considerations in our JIT compiler.
Both configurations pass 100% of [WebAssembly spec test suites]((https://github.com/WebAssembly/spec/tree/wg-1.0/test/core)) (on supported platforms).
| Runtime | Usage| amd64 | arm64 | others |
|:---:|:---:|:---:|:---:|:---:|
| Interpreter|`wazero.NewRuntimeConfigInterpreter()`|✅ |✅|✅|
| JIT |`wazero.NewRuntimeConfigJIT()`|✅|✅ |❌|
There are two runtime configurations supported in wazero: _JIT_ is default:
If you don't choose, ex `wazero.NewRuntime()`, JIT is used if supported. You can also force the interpreter like so:
```go
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter())
```
### Interpreter
Interpreter is a naive interpreter-based implementation of Wasm virtual
machine. Its implementation doesn't have any platform (GOARCH, GOOS) specific
code, therefore _interpreter_ can be used for any compilation target available
for Go (such as `riscv64`).
### JIT
JIT (Just In Time) compiles WebAssembly modules into machine code during
`Runtime.CompileModule` so that they are executed natively at runtime. JIT is
faster than Interpreter, often by order of magnitude (10x) or more. This is
done while still having no host-specific dependencies.
If interested, check out the [RATIONALE.md][8] and help us optimize further!
### Conformance
Both runtimes pass [WebAssembly 1.0 spectests][7] on supported platforms:
| Runtime | Usage| amd64 | arm64 | others |
|:---:|:---:|:---:|:---:|:---:|
| Interpreter|`wazero.NewRuntimeConfigInterpreter()`|✅ |✅|✅|
| JIT |`wazero.NewRuntimeConfigJIT()`|✅|✅ |❌|
## Support Policy
The below support policy focuses on compatability concerns of those embedding wazero into their Go applications.
The below support policy focuses on compatability concerns of those embedding
wazero into their Go applications.
### wazero
wazero is an early project, so APIs are subject to change until version 1.0.
We expect 1.0 to be at or before Q3 2022, so please practice the current APIs to ensure they work for you!
We expect [wazero 1.0][9] to be at or before Q3 2022, so please practice the
current APIs to ensure they work for you!
### Go
wazero has no dependencies except Go, so the only source of conflict in your project's use of Wazero is the Go version.
wazero has no dependencies except Go, so the only source of conflict in your
project's use of wazero is the Go version.
To simplify our support policy, we adopt Go's [Release Policy](https://go.dev/doc/devel/release) (two versions).
To simplify our support policy, we adopt Go's [Release Policy][10] (two versions).
This means wazero will remain compilable and tested on the the version prior to the latest release of Go.
This means wazero will remain compilable and tested on the version prior to the
latest release of Go.
For example, once Go 1.29 is released, wazero may choose to use a Go 1.28 feature.
For example, once Go 1.29 is released, wazero may use a Go 1.28 feature.
### Platform
@@ -135,7 +154,7 @@ systems are ones we test, but that doesn't necessarily mean other operating
system versions won't work.
We currently test Linux (Ubuntu and scratch), MacOS and Windows as packaged by
[GitHub Actions](https://github.com/actions/virtual-environments).
[GitHub Actions][11].
* Interpreter
* Linux is tested on amd64 (native) as well arm64 and riscv64 via emulation.
@@ -148,99 +167,78 @@ wazero has no dependencies and doesn't require CGO. This means it can also be
embedded in an application that doesn't use an operating system. This is a main
differentiator between wazero and alternatives.
We verify wazero's independence by running tests in Docker's [scratch image](https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch).
We verify zero dependencies by running tests in Docker's [scratch image][12].
This approach ensures compatibility with any parent image.
## Standards Compliance
## Specifications
wazero understands that while no-one desired to create confusion, confusion
exists both in what is a standard and what in practice is in fact a standard
feature. To help with this, we created some guidance both on the status quo
of WebAssembly portability and what we support.
The [WebAssembly Core Specification 1.0 (20191205)](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205)
is the only part of the WebAssembly ecosystem that is a W3C recommendation.
The WebAssembly Core Specification is the only specification relevant to
wazero, governed by a standards body. Release [1.0][1] is a Web Standard (REC).
Release [2.0][2] is a Working Draft (WD), so not yet a Web Standard.
In practice, this specification is not enough. Most compilers that target Wasm
rely on features that have not yet gone through W3C recommendation process,
such as `bulk-memory-operations`.
Many compilers implement system calls using the WebAssembly System Interface,
[WASI][5]. WASI is a WebAssembly community [subgroup][4], but has not published
any working drafts as a result of their work. WASI's last stable point was
[wasi_snapshot_preview1][13], tagged at the end of 2020.
Also, most compilers implement system calls using the WebAssembly System
Interface ([WASI](https://github.com/WebAssembly/WASI)). While WASI aims to be
a common layer for portability, it is not governed by a standards body, like
W3C. Moreover, while commonly implemented, WASI is not yet versioned. Its last
stable point was the "wasi_snapshot_preview1" tag released at the end of 2020.
While this seems scary, the confusion caused by non-standard features and
non-standard specifications is not as bad as it sounds. The WebAssembly
ecosystem is generally responsive regardless of where things are written down
and wazero provides tools, such as built-in support for WASI, to reduce pain.
While this seems scary, the confusion caused by pre-standard features is not as
bad as it sounds. The WebAssembly ecosystem is generally responsive regardless
of where things are written down and wazero provides tools, such as built-in
support for WASI, to reduce pain.
The goal of this section isn't to promote a W3C recommendation exclusive
approach, rather to help you understand common language around portable
features and which of those wazero supports at the moment. While we consider
features formalized through W3C recommendation status mandatory, we actively
pursue non-standard features as well interop with commonly used infrastructure
pursue pre-standard features as well interop with commonly used infrastructure
such as AssemblyScript.
In summary, we hope this section can guide you in terms of what wazero supports
as well as how to classify a request for a feature we don't yet support.
### WebAssembly Core
wazero supports the only WebAssembly specification which has reached W3C
Recommendation (REC) phase: [WebAssembly Core Specification 1.0 (20191205)](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205).
Independent verification is possible via the [WebAssembly spec test suite](https://github.com/WebAssembly/spec/tree/wg-1.0/test/core),
which we run on every change and against all supported platforms.
wazero conforms with spectests [7] defined alongside WebAssembly Core
Specification [1.0][1]. There is also [work in progress][14] towards release
[2.0][2], despite it not being a Web Standard, yet.
One current limitation of wazero is that it doesn't fully implement the Text
Format, yet, e.g. compiling `.wat` files. The intent is to finish this, and
meanwhile users can work around this using tools such as `wat2wasm` to compile
the text format into the binary format.
Format, yet, e.g. compiling `.wat` files. The intent is to [finish this][15],
and meanwhile users can work around this using tools such as `wat2wasm` to
compile the text format into the binary format. In practice, the text format is
too low level for most users, so delays here have limited impact.
#### Post 1.0 Features
#### Post 2.0 Features
Features regardless of W3C release are inventoried in the [Proposals][16].
repository. wazero implements [Finished Proposals][17] based on user demand,
using [wazero.RuntimeConfig][18] feature flags.
The last W3C REC was at the end of 2019. There were other features that didn't
make the cut or were developed in the years since. The community unofficially
refers to these as [Finished Proposals](https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md).
To ensure compatability, wazero does not opt-in to any non-standard feature by
default. However, the following status covers what's currently possible with
`wazero.RuntimeConfig`.
| Feature | Status |
|:-------------------------------------:|:------:|
| mutable-global | ✅ |
| nontrapping-float-to-int-conversions | ✅ |
| sign-extension-ops | ✅ |
| multi-value | ✅ |
| JS-BigInt-integration | N/A |
| reference-types | 👷‍♂️ |
| bulk-memory-operations | ✅ |
| simd | ❌ |
Note: While the above are specified in a WebAssembly GitHub repository, they
are not W3C recommendations (standards). This means they can change further
between now and any future update to the W3C WebAssembly core specification.
Due to this, we cannot guarantee future compatability. Please encourage the
[WebAssembly community](https://www.w3.org/community/webassembly/) to formalize
features you rely on, specifically to reach the W3C recommendation (REC) phase.
Features not yet assigned to a W3C release are not reliable. Encourage the
[WebAssembly community][19] to formalize features you rely on, so that they
become assigned to a release, and reach the W3C recommendation (REC) phase.
### WebAssembly System Interface (WASI)
As of early 2022, the WebAssembly System Interface (WASI) has never reached the
recommendation phase of the W3C. The closest to stability is a draft ([snapshot-01](https://github.com/WebAssembly/WASI/tree/snapshot-01))
released in late 2020. Some functions of this draft are used in practice while
some features are not known to be used at all. Further confusion exists because
some compilers (ex GrainLang) import functions not used. Finally, `snapshot-01`
includes features such as "rights" that [will be removed](https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844).
Many compilers implement system calls using the WebAssembly System Interface,
[WASI][5]. WASI is a WebAssembly community [subgroup][4], but has not published
any working drafts as a result of their work. WASI's last stable point was
[wasi_snapshot_preview1][13], tagged at the end of 2020.
Some functions in this tag are used in practice while some others are not known
to be used at all. Further confusion exists because some compilers, like
GrainLang, import functions not used. Finally, [wasi_snapshot_preview1][13]
includes features such as "rights" that [will be removed][20].
For all of these reasons, wazero will not implement all WASI features, just to
complete the below chart. If you desire something not yet implemented, please
[raise an issue](https://github.com/tetratelabs/wazero/issues/new) and include
your use case (ex which language you are using to compile, a.k.a. target Wasm).
<details><summary>Click to see the full list of supported WASI systemcalls</summary>
<details><summary>Click to see the full list of supported WASI functions</summary>
<p>
| Function | Status | Known Usage |
@@ -296,17 +294,16 @@ your use case (ex which language you are using to compile, a.k.a. target Wasm).
## History of wazero
wazero was originally developed by [Takeshi Yoneda](https://github.com/mathetake)
as a hobby project in mid 2020. In late 2021, it was sponsored by Tetrate as a
top-level project. That said, Takeshi's original motivation is as relevant
today as when he started the project, and worthwhile reading:
wazero was originally developed by [Takeshi Yoneda][21] as a hobby project in
mid 2020. In late 2021, it was sponsored by Tetrate as a top-level project.
That said, Takeshi's original motivation is as relevant today as when he
started the project, and worthwhile reading:
If you want to provide Wasm host environments in your Go programs, currently
there's no other choice than using CGO leveraging the state-of-the-art
runtimes written in C++/Rust (e.g. V8, Wasmtime, Wasmer, WAVM, etc.), and
there's no pure Go Wasm runtime out there. (There's only one exception named
[wagon](https://github.com/go-interpreter/wagon), but it was archived with the
mention to this project.)
[wagon][22], but it was archived with the mention to this project.)
First, why do you want to write host environments in Go? You might want to have
plugin systems in your Go project and want these plugin systems to be
@@ -315,21 +312,47 @@ languages. That's where Wasm comes into play. You write your own Wasm host
environments and embed Wasm runtime in your projects, and now users are able to
write plugins in their own favorite languages (AssemblyScript, C, C++, Rust,
Zig, etc.). As a specific example, you maybe write proxy severs in Go and want
to allow users to extend the proxy via [Proxy-Wasm ABI](https://github.com/proxy-wasm/spec).
Maybe you are writing server-side rendering applications via Wasm, or
[OpenPolicyAgent](https://www.openpolicyagent.org/docs/latest/wasm/) is using
Wasm for plugin system.
to allow users to extend the proxy via [Proxy-Wasm ABI][23]. Maybe you are
writing server-side rendering applications via Wasm, or [OpenPolicyAgent][24]
is using Wasm for plugin system.
However, experienced Golang developers often avoid using CGO because it
introduces complexity. For example, CGO projects are larger and complicated to
consume due to their libc + shared library dependency. Debugging is more
difficult for Go developers when most of a library is written in Rustlang.
[_CGO is not Go_](https://dave.cheney.net/2016/01/18/cgo-is-not-go)[ -- _Rob_ _Pike_](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=757s) dives in deeper.
In short, the primary motivation to start wazero was to avoid CGO.
[_CGO is not Go_][25] [ -- _Rob_ _Pike_][26] dives in deeper. In short, the
primary motivation to start wazero was to avoid CGO.
wazero compiles WebAssembly modules into native assembly (JIT) by default. You
may be surprised to find equal or better performance vs mature JIT-style
runtimes because [CGO is slow](https://github.com/golang/go/issues/19574). More
specifically, if you make large amount of CGO calls which cross the boundary
between Go and C (stack) space, then the usage of CGO could be a bottleneck.
runtimes because [CGO is slow][27]. More specifically, if you make large amount
of CGO calls which cross the boundary between Go and C (stack) space, then the
usage of CGO could be a bottleneck.
[1]: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/
[2]: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/
[3]: ./internal/integration_test/post1_0/multi-value/testdata/fac.wat
[4]: https://github.com/WebAssembly/meetings/blob/main/process/subgroups.md
[5]: https://github.com/WebAssembly/WASI
[6]: https://pkg.go.dev/golang.org/x/sys/unix
[7]: https://github.com/WebAssembly/spec/tree/wg-1.0/test/core
[8]: ./internal/wasm/jit/RATIONALE.md
[9]: https://github.com/tetratelabs/wazero/issues/506
[10]: https://go.dev/doc/devel/release
[11]: https://github.com/actions/virtual-environments
[12]: https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch
[13]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md
[14]: https://github.com/tetratelabs/wazero/issues/484
[15]: https://github.com/tetratelabs/wazero/issues/59
[16]: https://github.com/WebAssembly/proposals
[17]: https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md
[18]: https://pkg.go.dev/github.com/tetratelabs/wazero#RuntimeConfig
[19]: https://www.w3.org/community/webassembly/
[20]: https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844
[21]: https://github.com/mathetake
[22]: https://github.com/go-interpreter/wagon
[23]: https://github.com/proxy-wasm/spec
[24]: https://www.openpolicyagent.org/docs/latest/wasm/
[25]: https://dave.cheney.net/2016/01/18/cgo-is-not-go
[26]: https://www.youtube.com/watch?v=PAAkCSZUG1c&t=757s
[27]: https://github.com/golang/go/issues/19574

View File

@@ -1,35 +0,0 @@
;; This includes a factorial function that uses the "multi-value" feature
;;
;; Compile like so, in order to not add any other post 1.0 features to the resulting wasm.
;; wat2wasm \
;; --disable-saturating-float-to-int \
;; --disable-sign-extension \
;; --disable-simd \
;; --disable-bulk-memory \
;; --disable-reference-types \
;; --debug-names fac.wat
;;
;; See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
(module
(func $pick0 (param i64) (result i64 i64)
(local.get 0) (local.get 0)
)
(func $pick1 (param i64 i64) (result i64 i64 i64)
(local.get 0) (local.get 1) (local.get 0)
)
;; Note: This implementation loops forever if the input is zero.
(func $fac (param i64) (result i64)
(i64.const 1) (local.get 0)
(loop $l (param i64 i64) (result i64)
(call $pick1) (call $pick1) (i64.mul)
(call $pick1) (i64.const 1) (i64.sub)
(call $pick0) (i64.const 0) (i64.gt_u)
(br_if $l)
(drop) (return)
)
)
(export "fac" (func $fac))
)