1<div align="center"> 2 <h1>Wizer</h1> 3 4 <p> 5 <strong>The WebAssembly Pre-Initializer!</strong> 6 </p> 7 8 <strong>A <a href="https://bytecodealliance.org/">Bytecode Alliance</a> project</strong> 9 10 <p> 11 <a href="https://bytecodealliance.zulipchat.com/#narrow/stream/223391-wasm"><img src="https://img.shields.io/badge/zulip-join_chat-brightgreen.svg" alt="zulip chat" /></a> 12 <a href="https://docs.rs/wasmtime-wizer"><img src="https://docs.rs/wasmtime-wizer/badge.svg" alt="Documentation Status" /></a> 13 </p> 14 15 <h3> 16 <a href="https://docs.rs/wasmtime-wizer">API Docs</a> 17 <span> | </span> 18 <a href="https://github.com/bytecodealliance/wasmtime/blob/main/CONTRIBUTING.md">Contributing</a> 19 <span> | </span> 20 <a href="https://bytecodealliance.zulipchat.com/#narrow/stream/223391-wasm">Chat</a> 21 </h3> 22</div> 23 24* [About](#about) 25* [Install](#install) 26* [Example Usage](#example-usage) 27* [Caveats](#caveats) 28* [Using Wizer as a Library](#using-wizer-as-a-library) 29* [How Does it Work?](#how-does-it-work) 30 31## About 32 33Don't wait for your Wasm module to initialize itself, pre-initialize it! Wizer 34instantiates your WebAssembly module, executes its initialization function, and 35then snapshots the initialized state out into a new WebAssembly module. Now you 36can use this new, pre-initialized WebAssembly module to hit the ground running, 37without making your users wait for that first-time set up code to complete. 38 39The improvements to start up latency you can expect will depend on how much 40initialization work your WebAssembly module needs to do before it's ready. Some 41initial benchmarking shows between 1.35 to 6.00 times faster instantiation and 42initialization with Wizer, depending on the workload: 43 44| Program | Without Wizer | With Wizer | Speedup | 45|------------------------|--------------:|-----------:|-----------------:| 46| [`regex`][regex-bench] | 248.85 us | 183.99 us | **1.35x faster** | 47| [UAP][uap-bench] | 98.297 ms | 16.385 ms | **6.00x faster** | 48 49[regex-bench]: https://github.com/bytecodealliance/wasmtime/tree/main/crates/wizer/benches/regex-bench 50[uap-bench]: https://github.com/bytecodealliance/wasmtime/tree/main/crates/wizer/benches/uap-bench 51 52Not every program will see an improvement to instantiation and start up 53latency. For example, Wizer will often increase the size of the Wasm module's 54`Data` section, which could negatively impact network transfer times on the 55Web. However, the best way to find out if your Wasm module will see an 56improvement is to try it out! Adding an initialization function isn't too hard. 57 58Finally, you can likely see further improvements by running 59[`wasm-opt`][binaryen] on the pre-initialized module. Beyond the usual benefits 60that `wasm-opt` brings, the module likely has a bunch of initialization-only 61code that is no longer needed now that the module is already initialized, and 62which `wasm-opt` can remove. 63 64[binaryen]: https://github.com/WebAssembly/binaryen 65 66## Example Usage 67 68First, make sure your Wasm module exports an initialization function named 69`wizer-initialize`. For example, in Rust you can export it like this: 70 71```rust 72#[unsafe(export_name = "wizer-initialize")] 73pub extern "C" fn init() { 74 // Your initialization code goes here... 75} 76``` 77 78For a complete C++ example, see [this](https://github.com/bytecodealliance/wizer/tree/main/examples/cpp). 79 80Then, if your Wasm module is named `input.wasm`, run the `wizer` CLI: 81 82```shell-session 83wasmtime wizer input.wasm -o initialized.wasm 84``` 85 86Now you have a pre-initialized version of your Wasm module at 87`initialized.wasm`! 88 89More details, flags, and options can be found via `--help`: 90 91```shell-session 92wasmtime wizer --help 93``` 94 95## Caveats 96 97* The initialization function may not call any imported functions. Doing so will 98 trigger a trap and `wizer` will exit. You can, however, allow WASI calls via 99 the `--allow-wasi` flag. 100 101* The Wasm module may not import globals, tables, or memories. 102 103* Reference types are not supported yet. It isn't 100% clear yet what the best 104 approach to snapshotting `externref` tables is. 105 106## Using Wizer as a Library 107 108Add a dependency in your `Cargo.toml`: 109 110```shell-session 111cargo add wasmtime-wizer 112``` 113 114And then use the `wizer::Wizer` builder to configure and run Wizer: 115 116```rust 117use wizer::Wizer; 118 119let input_wasm = get_input_wasm_bytes(); 120let initialized_wasm_bytes = Wizer::new() 121 .run(&mut store, &input_wasm, |store, module| { 122 linker.instantiate(store, module) 123 })?; 124``` 125 126## How Does it Work? 127 128First we instantiate the input Wasm module with Wasmtime and run the 129initialization function. Then we record the Wasm instance's state: 130 131* What are the values of its globals? 132* What regions of memory are non-zero? 133 134Then we rewrite the Wasm binary by initializing its globals directly to their 135recorded state, and removing the module's old data segments and replacing them 136with data segments for each of the non-zero regions of memory we recorded. 137 138Want some more details? Check out the talk ["Hit the Ground Running: Wasm 139Snapshots for Fast Start 140Up"](https://fitzgeraldnick.com/2021/05/10/wasm-summit-2021.html) from the 2021 141WebAssembly Summit. 142