Table of Contents
I wanted to try a simple Rust+Wasm example. I’m following the instructions from - https://github.com/AndrewThian/learn-wasm-rust[1]. I created the project:
rustup target add wasm32-unknown-unknown cargo install wasm-gc cargo install wasm-bindgen-cli cargo new --lib 1952-learning-rust-wasm
Here’s how I compiled it:
cargo build --target wasm32-unknown-unknown --release wasm-gc target/wasm32-unknown-unknown/release/1952_learning_rust_wasm.wasm learning.gc.wasm
I had to add the application/wasm wasm mime type to the apache/nginx config.
Here’s the output:
The wasm-bindgen[2] tool generates javascript glue to handle types other than numbers. The --browser
flag makes a js module, and does not include the above code to load the wasm. The --target no-modules
flag makes a top level definition, and does include code to load the wasm. See these docs[3] for the glue code. This tool seems to automatically run wasm-gc
for you. See the list of types[4]: number, bool, str, char, arrays of js values, iterables[5], js functions[6], rust functions[7], promises/futures[8].
The js-sys[9] Rust library exposes all the JS APIs: data types (arrays, set, map, date, etc.), proxy, regexp, uri functions, exception objects, etc. The web-sys[10] Rust library exposes all the browser APIs: DOM, window, audio, svg, webgl, canvas, websockets[11], etc.
wasm-bindgen --debug --target no-modules target/wasm32-unknown-unknown/release/1952_learning_rust_wasm.wasm --out-dir build/
1 Size#
- simplest function ends up as 209 bytes (90,588 bytes before wasm-gc)
- with vec and heap allocation, 9305 bytes (270,020 bytes before wasm-gc)
Seems to 5835 bytes for heap allocation:
# twiggy top build/1952_learning_rust_wasm_bg.wasm | grep Dl 3236 ┊ 33.79% ┊ dlmalloc::dlmalloc::Dlmalloc::malloc::h363feeec79793de2 941 ┊ 9.83% ┊ dlmalloc::dlmalloc::Dlmalloc::free::h57aed881a8c806e8 651 ┊ 6.80% ┊ dlmalloc::dlmalloc::Dlmalloc::dispose_chunk::h1db030999ec3b24a 365 ┊ 3.81% ┊ dlmalloc::dlmalloc::Dlmalloc::memalign::ha7187a0adc17c42a 327 ┊ 3.41% ┊ dlmalloc::dlmalloc::Dlmalloc::insert_large_chunk::h1fcac6f829185c8b 315 ┊ 3.29% ┊ dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk::hafa48d776dcd75a2
# twiggy top build/1952_learning_rust_wasm_bg.wasm | grep Dl | awk '{sum += $1} END {print sum}' 5835
2 Sources#
Then edited Cargo.toml:
[package] name = "1952_learning_rust_wasm" version = "0.1.0" authors = ["Amit Patel <redblobgames@gmail.com>"] edition = "2018" [lib] crate-type = ["cdylib"] [profile.release] lto = true opt-level = 'z' [dependencies] wasm-bindgen = "0.2"
Here’s the source src/lib.rs
:
use wasm_bindgen::prelude::*; static MEMORY_TEST: &str = "Hello, World"; macro_rules! log { ($($t:tt)*) => (console_log_str(&format!($($t)*))) } #[wasm_bindgen] extern "C" { fn call_me_str(x: &str); #[wasm_bindgen(js_namespace = console, js_name = log)] fn console_log_str(s: &str); } #[wasm_bindgen] pub fn add_one(x: u32) -> u32 { x + 1 } #[wasm_bindgen] pub fn return_str(x: &str) -> String { x.to_string() } #[wasm_bindgen] pub fn return_vec(x: &str) -> Vec<u8> { x.to_string().into_bytes() } #[wasm_bindgen] pub fn return_array() -> *const u8 { MEMORY_TEST.as_ptr() } #[wasm_bindgen] pub fn return_arraylen() -> usize { MEMORY_TEST.len() } #[wasm_bindgen] pub fn pass_in_str(x: &str, y: String) -> String { let mut a = x.to_string(); a.push_str(&y); log!("pass_in_str({}, {}) -> {}", x, y, a); a } #[wasm_bindgen] pub fn call_fn(x: &str) { call_me_str(x); }
3 More#
- https://rustwasm.github.io/wasm-bindgen/reference/cli.html[12] - to see what wasm-bindgen generates, run the tool directly
- https://github.com/rustwasm/awesome-rust-and-webassembly[13] - list of links to resources