site: elaborates concurrency and TinyGo notes; adds Rust notes (#764)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -18,6 +18,6 @@ Under the covers, [lib.rs](testdata/src/lib.rs) does a few things of interest:
|
||||
Note: We chose to not use CString because it keeps the example similar to how
|
||||
you would track memory for arbitrary blobs. We also watched function signatures
|
||||
carefully as Rust compiles different WebAssembly signatures depending on the
|
||||
input type. All of this is Rust-specific, and wazero isn't a Rust project, but
|
||||
we hope this gets you started. For next steps, consider reading the
|
||||
[Rust and WebAssembly book](https://rustwasm.github.io/docs/book/).
|
||||
input type.
|
||||
|
||||
See https://wazero.io/languages/rust/ for more tips.
|
||||
|
||||
@@ -24,7 +24,7 @@ to allow users to extend the proxy via [Proxy-Wasm ABI][3]. Maybe you are
|
||||
writing server-side rendering applications via Wasm, or [OpenPolicyAgent][4]
|
||||
is using Wasm for plugin system.
|
||||
|
||||
However, experienced Golang developers often avoid using CGO because it
|
||||
However, experienced Go 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.
|
||||
|
||||
@@ -5,8 +5,8 @@ layout = "single"
|
||||
|
||||
WebAssembly has a virtual machine architecture where the host is the embedding
|
||||
process and the guest is a program compiled into the WebAssembly Binary Format,
|
||||
also known as wasm. The first step is to take a source file and compile it into
|
||||
the wasm bytecode.
|
||||
also known as Wasm. The first step is to take a source file and compile it into
|
||||
the Wasm bytecode.
|
||||
|
||||
Ex. If your source is in Go, you might compile it with TinyGo.
|
||||
```goat
|
||||
@@ -18,8 +18,9 @@ Ex. If your source is in Go, you might compile it with TinyGo.
|
||||
Below are notes wazero contributed so far, in alphabetical order by language.
|
||||
|
||||
* [TinyGo](tinygo) Ex. `tinygo build -o X.wasm -target=wasi X.go`
|
||||
* [Rust](rust) Ex. `rustc -o X.wasm --target wasm32-wasi X.rs`
|
||||
|
||||
wazero is a runtime that embeds in Golang applications, not a web browser. As
|
||||
wazero is a runtime that embeds in Go applications, not a web browser. As
|
||||
such, these notes bias towards backend use of WebAssembly, not browser use.
|
||||
|
||||
Disclaimer: These are not official documentation, nor represent the teams who
|
||||
@@ -27,5 +28,59 @@ maintain language compilers. If you see any errors, please help [maintain][1]
|
||||
these and [star our GitHub repository][2] if they are helpful. Together, we can
|
||||
make WebAssembly easier on the next person.
|
||||
|
||||
## Concurrency
|
||||
|
||||
WebAssembly does not yet support true parallelism; it lacks support for
|
||||
multiple threads, atomics, and memory barriers. (It may someday; See
|
||||
the [threads proposal][5].)
|
||||
|
||||
For example, a compiler targeting [WASI][3], generates a `_start` function
|
||||
corresponding to `main` in the original source code. When the WebAssembly
|
||||
runtime calls `_start`, it remains on the same thread of execution until that
|
||||
function completes.
|
||||
|
||||
Concretely, if using wazero, a Wasm function call remains on the calling
|
||||
goroutine until it completes.
|
||||
|
||||
In summary, while true that host functions can do anything, including launch
|
||||
processes, Wasm binaries compliant with [WebAssembly Core 2.0][4] cannot do
|
||||
anything in parallel, unless they use non-standard instructions or conventions
|
||||
not yet defined by the specification.
|
||||
|
||||
### Compiling Parallel Code to Serial Wasm
|
||||
|
||||
Until this [changes][5], language compilers cannot generate Wasm that can
|
||||
control scheduling within a function or safely modify memory in parallel.
|
||||
In other words, one function cannot do anything in parallel.
|
||||
|
||||
This impacts how programming language primitives translate to Wasm:
|
||||
|
||||
* Garbage collection invokes on the runtime host's calling thread instead of
|
||||
in the background.
|
||||
* Language-defined threads or co-routines fail compilation or are limited to
|
||||
sequential processing.
|
||||
* Locks and barriers fail compilation or are implemented unsafely.
|
||||
* Async functions including I/O execute sequentially.
|
||||
|
||||
Language compilers often used shared infrastructure, such as [LLVM][6] and
|
||||
[Binaryen][7]. One tool that helps in translation is Binaryen's [Asyncify][8],
|
||||
which lets a language support synchronous operations in an async manner.
|
||||
|
||||
### Concurrency via Orchestration
|
||||
|
||||
To work around lack of concurrency at the WebAssembly Core abstraction, tools
|
||||
often orchestrate pools of workers, and ensure a module in that pool is only
|
||||
used sequentially.
|
||||
|
||||
For example, [waPC][9] provides a WASM module pool, so host callbacks can be
|
||||
invoked in parallel, despite not being able to share memory.
|
||||
|
||||
[1]: https://github.com/tetratelabs/wazero/tree/main/site/content/languages
|
||||
[2]: https://github.com/tetratelabs/wazero/stargazers
|
||||
[3]: https://github.com/WebAssembly/WASI/blob/snapshot-01/design/application-abi.md#current-unstable-abi
|
||||
[4]: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/
|
||||
[5]: https://github.com/WebAssembly/threads
|
||||
[6]: https://llvm.org
|
||||
[7]: https://github.com/WebAssembly/binaryen
|
||||
[8]: https://github.com/WebAssembly/binaryen/blob/main/src/passes/Asyncify.cpp
|
||||
[9]: https://github.com/wapc/wapc-go
|
||||
|
||||
225
site/content/languages/rust.md
Normal file
225
site/content/languages/rust.md
Normal file
@@ -0,0 +1,225 @@
|
||||
+++
|
||||
title = "Rust"
|
||||
+++
|
||||
|
||||
## Introduction
|
||||
|
||||
Beginning with 1.30 [Rust][1] can generate `%.wasm` files instead of
|
||||
architecture-specific binaries through three targets:
|
||||
|
||||
* `wasm32-unknown-emscripten`: mostly for browser (JavaScript) use.
|
||||
* `wasm32-unknown-unknown`: for standalone use in or outside the browser.
|
||||
* `wasm32-wasi`: for use outside the browser.
|
||||
|
||||
This document is maintained by wazero, which is a WebAssembly runtime that
|
||||
embeds in Go applications. Hence, our notes focus on targets used outside the
|
||||
browser, tested by wazero: `wasm32-unknown-unknown` and `wasm32-wasi`.
|
||||
|
||||
This document also focuses on `rustc` as opposed to `cargo`, for precision and
|
||||
brevity.
|
||||
|
||||
## Overview
|
||||
|
||||
When Rust compiles a `%.rs` file with a `wasm32-*` target, the output `%.wasm`
|
||||
depends on a subset of features in the [WebAssembly 1.0 Core specification][2].
|
||||
The `wasm32-wasi` target depends on [WASI][3] host functions as well.
|
||||
|
||||
Unlike some compilers, Rust also supports importing custom host functions and
|
||||
exporting functions back to the host.
|
||||
|
||||
Here's a basic example of source in Rust:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
pub extern "C" fn add(x: i32, y: i32) -> i32 {
|
||||
x + y
|
||||
}
|
||||
```
|
||||
|
||||
The following is the minimal command to build a Wasm file.
|
||||
```bash
|
||||
rustc -o lib.wasm --target wasm32-unknown-unknown --crate-type cdylib lib.rs
|
||||
```
|
||||
|
||||
The resulting Wasm exports the `add` function so that the embedding host can
|
||||
call it, regardless of if the host is written in Rust or not.
|
||||
|
||||
### Digging Deeper
|
||||
|
||||
There are a few things to unpack above, so let's start at the top.
|
||||
|
||||
The rust source includes `#[no_mangle]` and `extern "C"`. Add these to
|
||||
functions you want to export to the WebAssembly host. You can read more about
|
||||
this in [The Embedded Rust Book][4].
|
||||
|
||||
Next, you'll notice the flag `--crate-type cdylib` passed to `rustc`. This
|
||||
compiles the source as a library, ex. without a `main` function.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This document includes notes contributed by the wazero community. While wazero
|
||||
includes Rust examples, the community is less familiar with Rust. For more
|
||||
help, consider the [Rust and WebAssembly book][5].
|
||||
|
||||
Meanwhile, please help us [maintain][6] this document and [star our GitHub
|
||||
repository][7], if it is helpful. Together, we can make WebAssembly easier on
|
||||
the next person.
|
||||
|
||||
## Constraints
|
||||
|
||||
Like other compilers that can target wasm, there are constraints using Rust.
|
||||
These constraints affect the library design and dependency choices in your
|
||||
source.
|
||||
|
||||
The most common constraint is which crates you can depend on. Please refer to
|
||||
the [Which Crates Will Work Off-the-Shelf with WebAssembly?][8] page in the
|
||||
[Rust and WebAssembly book][5] for more on this.
|
||||
|
||||
## Memory
|
||||
|
||||
When Rust compiles rust into Wasm, it configures the WebAssembly linear memory
|
||||
to an initial size of 17 pages (1.1MB), and marks a position in that memory as
|
||||
the heap base. All memory beyond that is used for the Rust heap.
|
||||
|
||||
Allocations within Rust (compiled to `%.wasm`) are managed as one would expect.
|
||||
The `global_allocator` can allocate pages (`alloc_pages`) until `memory.grow`
|
||||
on the host returns -1.
|
||||
|
||||
### Host Allocations
|
||||
|
||||
Sometimes a host function needs to allocate memory directly. For example, to
|
||||
write JSON of a given length before invoking an exported function to parse it.
|
||||
|
||||
The below snippet is a realistic example of a function exported to the host,
|
||||
who needs to allocate memory first.
|
||||
```rust
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn configure(ptr: u32, len: u32) {
|
||||
let json = &ptr_to_string(ptr, len);
|
||||
}
|
||||
```
|
||||
Note: WebAssembly uses 32-bit memory addressing, so a `uintptr` is 32-bits.
|
||||
|
||||
The general flow is that the host allocates memory by calling an allocation
|
||||
function with the size needed. Then, it writes data, in this case JSON, to the
|
||||
memory offset (`ptr`). At that point, it can call a host function, ex
|
||||
`configure`, passing the `ptr` and `size` allocated. The guest Wasm (compiled
|
||||
from Rust) will be able to read the data. To ensure no memory leaks, the host
|
||||
calls a free function, with the same `ptr`, afterwards and unconditionally.
|
||||
|
||||
Note: wazero includes an [example project][9] that shows this.
|
||||
|
||||
To allow the host to allocate memory, you need to define your own `malloc` and
|
||||
`free` functions:
|
||||
```webassembly
|
||||
(func (export "malloc") (param $size i32) (result (;$ptr;) i32))
|
||||
(func (export "free") (param $ptr i32) (param $size i32))
|
||||
```
|
||||
|
||||
The below implements this in Rustlang:
|
||||
```rust
|
||||
use std::mem::MaybeUninit;
|
||||
use std::slice;
|
||||
|
||||
unsafe fn ptr_to_string(ptr: u32, len: u32) -> String {
|
||||
let slice = slice::from_raw_parts_mut(ptr as *mut u8, len as usize);
|
||||
let utf8 = std::str::from_utf8_unchecked_mut(slice);
|
||||
return String::from(utf8);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn alloc(size: u32) -> *mut u8 {
|
||||
// Allocate the amount of bytes needed.
|
||||
let vec: Vec<MaybeUninit<u8>> = Vec::with_capacity(size as usize);
|
||||
|
||||
// into_raw leaks the memory to the caller.
|
||||
Box::into_raw(vec.into_boxed_slice()) as *mut u8
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn free(ptr: u32, size: u32) {
|
||||
// Retake the pointer which allows its memory to be freed.
|
||||
let _ = Vec::from_raw_parts(ptr as *mut u8, 0, size as usize);
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, the above code is quite technical and should be kept separate
|
||||
from your business logic as much as possible.
|
||||
|
||||
## System Calls
|
||||
|
||||
WebAssembly is a stack-based virtual machine specification, so operates at a
|
||||
lower level than an operating system. For functionality the operating system
|
||||
would otherwise provide, you must use the `wasm32-wasi` target. This imports
|
||||
host functions defined in [WASI][3], described in [Specifications]({{< ref "/specs" >}}).
|
||||
|
||||
For example, `rustc -o hello.wasm --target wasm32-wasi hello.rs` compiles the
|
||||
below `main` function into a WASI function exported as `_start`.
|
||||
```rust
|
||||
fn main() {
|
||||
println!("Hello World!");
|
||||
}
|
||||
```
|
||||
|
||||
Note: wazero includes an [example WASI project][10] including [source code][11]
|
||||
that implements `cat` without any WebAssembly-specific code.
|
||||
|
||||
## Concurrency
|
||||
|
||||
Please read our overview of WebAssembly and
|
||||
[concurrency]({{< ref "_index.md#concurrency" >}}). In short, the current
|
||||
WebAssembly specification does not support parallel processing.
|
||||
|
||||
## Optimizations
|
||||
|
||||
Below are some commonly used configurations that allow optimizing for size or
|
||||
performance vs defaults. Note that sometimes one sacrifices the other.
|
||||
|
||||
### Binary size
|
||||
|
||||
Those with `%.wasm` binary size constraints can change their source or set
|
||||
`rustc` flags to reduce it.
|
||||
|
||||
Source changes:
|
||||
* [wee_alloc][12]: Smaller, WebAssembly-tuned memory allocator.
|
||||
|
||||
[`rustc` flags][13]:
|
||||
* `-C debuginfo=0`: Strips DWARF, but retains the WebAssembly name section.
|
||||
* `-C opt-level=3`: Includes all size optimizations.
|
||||
|
||||
Those using cargo should also use the `--release` flag, which corresponds to
|
||||
`rustc -C debuginfo=0 -C opt-level=3`.
|
||||
|
||||
Those using the `wasm32-wasi` target should consider the [cargo-wasi][14] crate
|
||||
as it dramatically reduces Wasm size.
|
||||
|
||||
### Performance
|
||||
|
||||
Those with runtime performance constraints can change their source or set
|
||||
`rustc` flags to improve it.
|
||||
|
||||
[`rustc` flags][13]:
|
||||
* `-C opt-level=2`: Enable additional optimizations, frequently at the expense
|
||||
of binary size.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### Why is my `%.wasm` binary so big?
|
||||
Rust defaults can be overridden for those who can sacrifice features or
|
||||
performance for a [smaller binary](#binary-size). After that, tuning your
|
||||
source code may reduce binary size further.
|
||||
|
||||
[1]: https://www.rust-lang.org/tools/install
|
||||
[2]: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/
|
||||
[3]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md
|
||||
[4]: https://docs.rust-embedded.org/book/interoperability/rust-with-c.html#no_mangle
|
||||
[5]: https://rustwasm.github.io/docs/book
|
||||
[6]: https://github.com/tetratelabs/wazero/tree/main/site/content/languages/rust.md
|
||||
[7]: https://github.com/tetratelabs/wazero/stargazers
|
||||
[8]: https://rustwasm.github.io/docs/book/reference/which-crates-work-with-wasm.html
|
||||
[9]: https://github.com/tetratelabs/wazero/tree/main/examples/allocation/rust
|
||||
[10]: https://github.com/tetratelabs/wazero/tree/main/examples/wasi
|
||||
[11]: https://github.com/tetratelabs/wazero/tree/main/examples/wasi/testdata/cargo-wasi
|
||||
[12]: https://github.com/rustwasm/wee_alloc
|
||||
[13]: https://doc.rust-lang.org/cargo/reference/profiles.html#profile-settings
|
||||
[14]: https://github.com/bytecodealliance/cargo-wasi
|
||||
@@ -11,18 +11,18 @@ title = "TinyGo"
|
||||
* `wasi`: for use outside the browser.
|
||||
|
||||
This document is maintained by wazero, which is a WebAssembly runtime that
|
||||
embeds in Golang applications. Hence, all notes below will be about TinyGo's
|
||||
embeds in Go applications. Hence, all notes below will be about TinyGo's
|
||||
`wasi` target.
|
||||
|
||||
## Overview
|
||||
|
||||
When TinyGo compiles a `%.go` file with its `wasi` target, the output `%.wasm`
|
||||
depends on a subset of features in the [WebAssembly 2.0 Core specification][2],
|
||||
as well [WASI][3] host imports.
|
||||
as well [WASI][3] host functions.
|
||||
|
||||
Unlike some compilers, TinyGo also supports importing custom host functions and
|
||||
exporting functions back to the host.
|
||||
|
||||
## Example
|
||||
|
||||
Here's a basic example of source in TinyGo:
|
||||
|
||||
```go
|
||||
@@ -34,7 +34,7 @@ func add(x, y uint32) uint32 {
|
||||
}
|
||||
```
|
||||
|
||||
The following flags will result in the most compact (smallest) wasm file.
|
||||
The following is the minimal command to build a `%.wasm` binary.
|
||||
```bash
|
||||
tinygo build -o main.wasm -target=wasi main.go
|
||||
```
|
||||
@@ -60,6 +60,7 @@ These constraints affect the library design and dependency choices in your Go
|
||||
source.
|
||||
|
||||
### Partial Reflection Support
|
||||
|
||||
The first constraint people notice is that `encoding/json` usage compiles, but
|
||||
panics at runtime.
|
||||
```go
|
||||
@@ -83,6 +84,7 @@ tools][18] also. See [Frequently Asked Questions](#frequently-asked-questions)
|
||||
for some workarounds.
|
||||
|
||||
### Unimplemented System Calls
|
||||
|
||||
You may also notice some other features not yet work. For example, the below
|
||||
will compile, but print "readdir unimplemented : errno 54" at runtime.
|
||||
|
||||
@@ -103,6 +105,7 @@ standard way to stub a syscall until it is implemented. If you are interested
|
||||
in more, see [System Calls](#system-calls).
|
||||
|
||||
### Mitigating Constraints
|
||||
|
||||
Realities like this are not unique to TinyGo as they will happen compiling any
|
||||
language not written specifically with WebAssembly in mind. Knowing the same
|
||||
code compiled to wasm may return errors or worse panic, the main mitigation
|
||||
@@ -116,15 +119,16 @@ is also a much more efficient means to communicate bugs vs ad-hoc reports.
|
||||
|
||||
When TinyGo compiles go into wasm, it configures the WebAssembly linear memory
|
||||
to an initial size of 2 pages (16KB), and marks a position in that memory as
|
||||
the heap base. All memory beyond that is used for the Go heap, which can
|
||||
[grow][20] until `memory.grow` on the host returns -1.
|
||||
the heap base. All memory beyond that is used for the Go heap.
|
||||
|
||||
Allocations within Go (compiled to `%.wasm`) are managed as one would expect.
|
||||
Sometimes a host function needs to allocate memory directly. For example, to
|
||||
write JSON of a given length before invoking an exported function to parse it.
|
||||
The allocator can [grow][20] until `memory.grow` on the host returns -1.
|
||||
|
||||
### Host Allocations
|
||||
|
||||
Sometimes a host function needs to allocate memory directly. For example, to
|
||||
write JSON of a given length before invoking an exported function to parse it.
|
||||
|
||||
The below snippet is a realistic example of a function exported to the host,
|
||||
who needs to allocate memory first.
|
||||
```go
|
||||
@@ -220,11 +224,14 @@ approach later.
|
||||
|
||||
WebAssembly is a stack-based virtual machine specification, so operates at a
|
||||
lower level than an operating system. For functionality the operating system
|
||||
would otherwise provide, TinyGo imports host functions, specifically ones
|
||||
defined in [WASI][3], described in [Specifications]({{< ref "/specs" >}}).
|
||||
would otherwise provide, TinyGo imports host functions defined in [WASI][3],
|
||||
described in [Specifications]({{< ref "/specs" >}}).
|
||||
|
||||
Notably, if you compile and run below program with the target `wasi`, you'll
|
||||
see that the effective `GOARCH=wasm` and `GOOS=linux`.
|
||||
For example, `tinygo build -o main.wasm -target=wasi main.go` compiles the
|
||||
below `main` function into a WASI function exported as `_start`.
|
||||
|
||||
When the WebAssembly runtime calls `_start`, you'll see the effective
|
||||
`GOARCH=wasm` and `GOOS=linux`.
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -239,6 +246,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
Note: wazero includes an [example WASI project][21] including [source code][22]
|
||||
that implements `cat` without any WebAssembly-specific code.
|
||||
|
||||
### WASI Internals
|
||||
|
||||
While developing WASI in TinyGo is outside the scope of this document, the
|
||||
@@ -260,13 +270,19 @@ is stubbed (returns `syscall.ENOSYS`), in [syscall_libc_wasi.go][15].
|
||||
|
||||
## Concurrency
|
||||
|
||||
Current versions of the WebAssembly specification do not support parallelism,
|
||||
such as threads or atomics needed to safely work in parallel.
|
||||
Please read our overview of WebAssembly and
|
||||
[concurrency]({{< ref "_index.md#concurrency" >}}). In short, the current
|
||||
WebAssembly specification does not support parallel processing.
|
||||
|
||||
TinyGo, however, supports goroutines by default and acts like `GOMAXPROCS=1`.
|
||||
Tinygo uses only one core/thread regardless of target. This happens to be a
|
||||
good match for Wasm's current lack of support for (multiple) threads. Tinygo's
|
||||
goroutine scheduler on Wasm currently uses Binaryen's [Asyncify][23], a Wasm
|
||||
postprocessor also used by other languages targeting Wasm to provide similar
|
||||
concurrency.
|
||||
|
||||
For example, the following code will run with the expected output, even if
|
||||
the goroutines are defined in opposite dependency order.
|
||||
In summary, TinyGo supports goroutines by default and acts like `GOMAXPROCS=1`.
|
||||
Since [goroutines are not threads][24], the following code will run with the
|
||||
expected output, despite goroutines defined in opposite dependency order.
|
||||
```go
|
||||
package main
|
||||
|
||||
@@ -288,9 +304,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
However, creating goroutines after main (`_start` in WASI) has undefined
|
||||
behavior. For example, if that same function was exported (`//export:notMain`),
|
||||
and called after main, the line that creates a goroutine panics at runtime.
|
||||
There are some glitches to this. For example, if that same function was
|
||||
exported (`//export notMain`), and called while main wasn't running, the line
|
||||
that creates a goroutine currently [panics at runtime][25].
|
||||
|
||||
Given problems like this, some choose a compile-time failure instead, via
|
||||
`-scheduler=none`. Since code often needs to be custom in order to work with
|
||||
@@ -303,17 +319,21 @@ performance vs defaults. Note that sometimes one sacrifices the other.
|
||||
|
||||
### Binary size
|
||||
|
||||
Those with size constraints can reduce the `%.wasm` binary size by changing
|
||||
`tinygo` flags. For example, a simple `cat` program can reduce from default of
|
||||
260KB to 60KB using both flags below.
|
||||
Those with `%.wasm` binary size constraints can set `tinygo` flags to reduce
|
||||
it. For example, a simple `cat` program can reduce from default of 260KB to
|
||||
60KB using both flags below.
|
||||
|
||||
* `-scheduler=none`: Reduces size, but fails at compile time on goroutines.
|
||||
* `--no-debug`: Strips DWARF, but retains the WebAssembly name section.
|
||||
|
||||
### Performance
|
||||
|
||||
Those with runtime performance constraints can set `tinygo` flags to improve
|
||||
it.
|
||||
|
||||
* `-gc=leaking`: Avoids GC which improves performance for short-lived programs.
|
||||
* `-opt=2`: Can also improve performance.
|
||||
* `-opt=2`: Enable additional optimizations, frequently at the expense of binary
|
||||
size.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
@@ -332,7 +352,7 @@ when their neither has a main function nor uses memory. At least implementing
|
||||
A bare or standalone WebAssembly target doesn't yet exist, but if interested,
|
||||
you can follow [this issue][19].
|
||||
|
||||
### Why is my wasm so big?
|
||||
### Why is my `%.wasm` binary so big?
|
||||
TinyGo defaults can be overridden for those who can sacrifice features or
|
||||
performance for a [smaller binary](#binary-size). After that, tuning your
|
||||
source code may reduce binary size further.
|
||||
@@ -344,7 +364,7 @@ functions, such as `fmt.Println`, which can require 100KB of wasm.
|
||||
|
||||
[1]: https://tinygo.org/
|
||||
[2]: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/
|
||||
[3]: https://github.com/WebAssembly/WASI
|
||||
[3]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md
|
||||
[4]: https://tinygo.org/docs/guides/webassembly/
|
||||
[5]: https://github.com/tinygo-org/tinygo#getting-help
|
||||
[6]: https://github.com/tetratelabs/wazero/tree/main/site/content/languages/tinygo.md
|
||||
@@ -362,3 +382,8 @@ functions, such as `fmt.Println`, which can require 100KB of wasm.
|
||||
[18]: https://github.com/tinygo-org/tinygo/issues/447
|
||||
[19]: https://github.com/tinygo-org/tinygo/issues/3068
|
||||
[20]: https://github.com/tinygo-org/tinygo/blob/v0.25.0/src/runtime/arch_tinygowasm.go#L47-L62
|
||||
[21]: https://github.com/tetratelabs/wazero/tree/main/examples/wasi
|
||||
[22]: https://github.com/tetratelabs/wazero/tree/main/examples/wasi/testdata/tinygo
|
||||
[23]: https://github.com/WebAssembly/binaryen/blob/main/src/passes/Asyncify.cpp
|
||||
[24]: http://tleyden.github.io/blog/2014/10/30/goroutines-vs-threads/
|
||||
[25]: https://github.com/tinygo-org/tinygo/issues/3095
|
||||
|
||||
Reference in New Issue
Block a user