Running WebAssembly outside of the browser
Tags: rust, webassembly
Published: 2019-08-03 14:02:33

This is the third article in a series of posts on Rust, WebAssembly and Genetic Algorithms. If you haven't read the [first](https://dev.to/d3spis3d/genetic-algorithm-in-rust-3gg) or [second](https://dev.to/d3spis3d/genetic-algorithm-in-the-browser-with-webassembly-1e97) articles in this series it's definitely worth going back to them before continuing. In this article I will talk about Wasmtime, a runtime for executing WebAssembly outside of the browser. I'll take the algorithm developed in the first article in this series, build some extra features for improved command line usage, compile to WebAssembly and run the WebAssembly module from the command line with Wasmtime.

The complete code for this post can be found [here](https://github.com/d3spis3d/wasi-genetic).

![Abstract image of green and white swirls](https://thepracticaldev.s3.amazonaws.com/i/wdf2e4c43o3wquj2xop9.jpg)
Photo by [Darío Méndez](https://unsplash.com/@dariomen?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/t/experimental?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

The first improvement I've made to the Rust code from the first post in this series is to take the algorithm parameters as command line arguments. To enable this I've added the `structopt` [crate](https://crates.io/crates/structopt), which builds on the popular `clap` [crate](https://crates.io/crates/clap), and allows the definition of command line arguments using a struct. To define the CLI arguments a struct is defined and used with a macro and custom derive from `structopt`.

```rust
#[derive(StructOpt)]
#[structopt()]
struct Opt {
    #[structopt(name = "iterations")]
    iterations: usize,
    #[structopt(name = "pop_size")]
    population_size: usize,
    #[structopt(name = "crossover_rate")]
    crossover_rate: f64,
    #[structopt(name = "mutation_rate")]
    mutation_rate: f64,
    #[structopt(name = "survival_rate")]
    survival_rate: f64,
    #[structopt(name = "csv", parse(from_os_str))]
    csv: PathBuf,
}

fn main() {
    let opts = Opt::from_args();
    ...
}
```

The second change is to parse the list of cities for the travelling salesman problem from a CSV file. The CSV will have two columns, the first being the x co-ordinate and the second being the y co-ordinate for each city. The first row of the CSV file will contain a header with the column names (x and y) and this will allow the rows to be deserialised into the **City** struct by the `csv` [crate](https://crates.io/crates/csv) when they are read in.

```rust
#[derive(Deserialize)]
pub struct City {
    x: f64,
    y: f64,
}

fn main() {
    ...
    let mut reader = Reader::from_path(opts.csv).unwrap();
    let cities: Vec<City> = reader.deserialize()
        .map(|r| {
            let result: City = r.unwrap();
            result
        })
        .collect();

    ...
}
```

To get started with Wasmtime you will need to compile it from source. The full details on getting setup can be found [here](https://github.com/CraneStation/wasmtime/), but for MacOS this involved:

```bash
brew install cmake llvm

git clone --recurse-submodules https://github.com/CraneStation/wasmtime.git

cd wasmtime

cargo build
```

Once Wasmtime is compiled the next step is to ensure the necessary compile target for WebAssembly is available. Wasmtime uses the WebAssembly System Interface (WASI), which provides WebAssembly code with access to operating system features such as the filesystem. Adding the right compile target and compiling the Rust code to WebAssembly is done using:

```bash
rustup target add wasm32-wasi

cargo build --target wasm32-wasi --release
```

And finally running the WebAssembly Genetic Algorithm on the command line with Wasmtime. WebAssembly's security model involves sandboxing, this means that to enable the program to access files from the operating system the Wasmtime runtime needs a list of directories that the program will should be allowed to access. In this case the current directory `.` is provided so that the WebAssembly module can access the cities.csv file there.


```bash
../wasmtime/target/release/wasmtime --dir=. target/wasm32-wasi/release/wasi-genetic.wasm 5000 500 0.4 0.001 0.3 cities.csv
```

Thanks for reading this series of posts on Rust, WebAssembly and Genetic Algorithm. Any questions, feedback or comments are welcome here or on the repositories listed. The complete code for this post can be found [here](https://github.com/d3spis3d/wasi-genetic).