Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Add wee_alloc section #542

Merged
merged 1 commit into from
Feb 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- [`Cargo.toml`](./tutorial/template-deep-dive/cargo-toml.md)
- [`src/lib.rs`](./tutorial/template-deep-dive/src-lib-rs.md)
- [`src/utils.rs`](./tutorial/template-deep-dive/src-utils-rs.md)
- [`wee_alloc`](./tutorial/template-deep-dive/wee_alloc.md)
- [Packaging and Publishing](./tutorial/packaging-and-publishing.md)
- [Using your Library](./tutorial/using-your-library.md)
- [`Cargo.toml` Configuration](./cargo-toml-configuration.md)
Expand Down
35 changes: 5 additions & 30 deletions docs/src/tutorial/template-deep-dive/src-lib-rs.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,7 @@ use cfg_if::cfg_if;

`use` allows us to conveniently refer to parts of a crate or module. For example, suppose the crate `cfg_if` contains a function `func`. It is always possible to call this function directly by writing `cfg_if::func()`. However, this is often tedious to write. If we first specify `use cfg_if::func;`, then `func` can be called by just writing `func()` instead.

With this in mind, this `use` allows us to call the macro `cfg_if!` inside the crate `cfg_if` without writing `cfg_if::cfg_if!`.

```rust
use wasm_bindgen::prelude::*;
```

Many modules contain a prelude, a list of things that should be automatically imported. This allows common features of the module to be conveniently accessed without a lengthy prefix. For example, in this file we can use `#[wasm_bindgen]` only because it is brought into scope by the prelude.

The asterisk at the end of this `use` indicates that everything inside the module `wasm_bindgen::prelude` (i.e. the module `prelude` inside the crate `wasm_bindgen`) can be referred to without prefixing it with `wasm_bindgen::prelude`.

For example, `#[wasm_bindgen]` could also be written as `#[wasm_bindgen::prelude::wasm_bindgen]`, although this is not recommended.

## 3. `wee_alloc` optional dependecy
With this in mind, this `use` allows us to call the macro `cfg_if!` inside the crate `cfg_if` without writing `cfg_if::cfg_if!`. We use `cfg_if!` to configure `wee_alloc`, which we will talk more about in a [separate section](./wee_alloc.md):

```rust
cfg_if! {
Expand All @@ -96,32 +84,19 @@ cfg_if! {
}
```

This code block is intended to initialize `wee_alloc` as the global memory allocator, but only if the `wee_alloc` feature is enabled in `Cargo.toml`.

We immediately notice that `cfg_if!` is a macro because it ends in `!`, similarly to other Rust macros such as `println!` and `vec!`. A macro is directly replaced by other code during compile time.

During compile time, `cfg_if!` evaluates the `if` statement. This tests whether the feature `wee_alloc` is present in the `[features]` section of `Cargo.toml` (among other possible ways to set it).

As we saw earlier, the `default` vector in `[features]` only contains `"console_error_panic_hook"` and not `"wee_alloc"`. So, in this case, the `cfg_if!` block will be replaced by no code at all, and hence the default memory allocator will be used instead of `wee_alloc`.

```rust
extern crate wee_alloc;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
use wasm_bindgen::prelude::*;
```

However, suppose `"wee_alloc"` is appended to the `default` vector in `Cargo.toml`. Then, the `cfg_if!` block is instead replaced with the contents of the `if` block, shown above.

This code sets the `wee_alloc` allocator to be used as the global memory allocator.

### What is `wee_alloc`?

Reducing the size of compiled WebAssembly code is important, since it is often transmitted over the Internet or placed on embedded devices.

> `wee_alloc` is a tiny allocator designed for WebAssembly that has a (pre-compression) code-size footprint of only a single kilobyte.
Many modules contain a prelude, a list of things that should be automatically imported. This allows common features of the module to be conveniently accessed without a lengthy prefix. For example, in this file we can use `#[wasm_bindgen]` only because it is brought into scope by the prelude.

[An analysis](http://fitzgeraldnick.com/2018/02/09/wee-alloc.html) suggests that over half of the bare minimum WebAssembly memory footprint is required by Rust's default memory allocator. Yet, WebAssembly code often does not require a sophisticated allocator, since it often just requests a couple of large initial allocations.
The asterisk at the end of this `use` indicates that everything inside the module `wasm_bindgen::prelude` (i.e. the module `prelude` inside the crate `wasm_bindgen`) can be referred to without prefixing it with `wasm_bindgen::prelude`.

`wee_alloc` trades off size for speed. Although it has a tiny code-size footprint, it is relatively slow if additional allocations are needed.
For example, `#[wasm_bindgen]` could also be written as `#[wasm_bindgen::prelude::wasm_bindgen]`, although this is not recommended.

For more details, see the [`wee_alloc` repository](https://github.com/rustwasm/wee_alloc).
54 changes: 54 additions & 0 deletions docs/src/tutorial/template-deep-dive/wee_alloc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# wee_alloc

1. [What is `wee_alloc`?](#what-is-wee_alloc)
2. [Enabling `wee_alloc`](#enabling-wee_alloc)
3. [Rust nightly](#rust-nightly)

## What is `wee_alloc`?

Reducing the size of compiled WebAssembly code is important, since it is often transmitted over the Internet or placed on embedded devices.

> `wee_alloc` is a tiny allocator designed for WebAssembly that has a (pre-compression) code-size footprint of only a single kilobyte.

[An analysis](http://fitzgeraldnick.com/2018/02/09/wee-alloc.html) suggests that over half of the bare minimum WebAssembly memory footprint is required by Rust's default memory allocator. Yet, WebAssembly code often does not require a sophisticated allocator, since it often just requests a couple of large initial allocations.

`wee_alloc` trades off size for speed. Although it has a tiny code-size footprint, it is relatively slow if additional allocations are needed.

For even more details, see the [`wee_alloc` repository](https://github.com/rustwasm/wee_alloc).

## Enabling `wee_alloc`

In `lib.rs`, we have the configuration for `wee_alloc` inside a `cfg_if!` macro:

```rust
cfg_if! {
if #[cfg(feature = "wee_alloc")] {
extern crate wee_alloc;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
}
}
```

This code block is intended to initialize `wee_alloc` as the global memory allocator, but only if the `wee_alloc` feature is enabled in `Cargo.toml`.

To do so we need to append `"wee_alloc"` to the `default` vector in `Cargo.toml`. Then, the `cfg_if!` block is replaced with the contents of the `if` block, shown above.

```toml
[features]
default = ["console_error_panic_hook", "wee_alloc"]
```

## Rust nightly

`wee_alloc` currently relies on features only available in Rust nightly. As such it requires you to use the nightly toolchain for compilation. If you have [Rustup](https://rustup.rs/) set up, you can install the nightly toolchain as follows:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, wee_alloc will work on stable Rust next Thursday


```
rustup toolchain add nightly
```

To use `wasm-pack` with Rust nightly run:

```
rustup run nightly wasm-pack build
```