Skip to content
This repository has been archived by the owner on Jul 16, 2020. It is now read-only.

Commit

Permalink
Implement performance benchmarking for basic demo
Browse files Browse the repository at this point in the history
  • Loading branch information
mbestavros committed Sep 4, 2019
1 parent 33b893a commit a8aa10b
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 11 deletions.
16 changes: 13 additions & 3 deletions wasmtime-basic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This is an example crate demonstrating how Enarx may use Wasmtime, a Rust-powere

## Running the demo

By default, the Rust demo should run with `cargo run` out of the box.
The demo requires Rust nightly. If that's set up, the Rust demo should run with `cargo +nightly run` out of the box.

If you wish to compile the C demo, you'll need to install `lld` . On Fedora, this can be accomplished with `sudo dnf install lld`.

Expand All @@ -15,7 +15,17 @@ The WASM binary used for the demo can be compiled from either Rust or C. Compila
Rust is compiled by default. If C is desired, the appropriate feature can be invoked via the `cargo` command:

```
cargo run --no-default-features --features c
cargo +nightly run --no-default-features --features c
```

Or, alternatively, by changing the `default` feature in `Cargo.toml` from `["rust"]` to `["c"]`.
Or, alternatively, by changing the `default` feature in `Cargo.toml` from `["rust"]` to `["c"]`.

## Running benchmarks

`main.rs` includes performance benchmarks useful for analyzing the startup cost and runtime of functions in Wasmtime.

These benchmarks use Rust's unstable built-in benchmarking tools, and must be run on Rust nightly:

```
cargo +nightly bench
```
79 changes: 71 additions & 8 deletions wasmtime-basic/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
//! Rust-powered JIT, to natively run programs from several different source
//! languages (Rust/C/C++) compiled to WASI-compliant WASM.
#![feature(test)]

extern crate test;

use cranelift_codegen::settings;
use cranelift_native;
use std::fs::File;
use std::io::Read;
use wasmtime_jit::{ActionOutcome, Context, RuntimeValue};
use wasmtime_jit::{ActionError, ActionOutcome, Context, RuntimeValue};

// The basic WASM demo itself.
fn main() {
// Before we begin, it'll be heplful to know which source language we're
// running, so let's print it out.
Expand All @@ -18,11 +23,22 @@ fn main() {
println!("WASM binary has been compiled from Rust.");
}

println!("Loading WASM binary...");
println!("Loading and running WASM binary...");
let result = wasm_add_full();
println!("Finished. Results:");
match result.unwrap() {
ActionOutcome::Returned { values } => println!("Output: {:#?}", values),
ActionOutcome::Trapped { message } => println!("Trap from within function: {}", message),
}
println!("Done.");
}

// A function to encapsulate the full setup and execution of a single iteration of the WASM demo.
pub fn wasm_add_full() -> Result<ActionOutcome, ActionError> {
// First, we need to load the WASM binary in.
let mut binary_file = File::open(concat!(env!("OUT_DIR"), "/add.wasm")).unwrap();
let mut binary: Vec<u8> = Vec::new();
binary_file.read_to_end(&mut binary).unwrap();
println!("WASM binary loaded.");

// In order to run this binary, we need to prepare a few inputs.

Expand All @@ -40,12 +56,59 @@ fn main() {

// And, finally, invoke our function and print the results.
// For this demo, all we're doing is adding 5 and 7 together.
println!("Invoking function.");
let args = [RuntimeValue::I32(5), RuntimeValue::I32(7)];
let result = context.invoke(&mut instance, "add", &args);
match result.unwrap() {
ActionOutcome::Returned { values } => println!("Output: {:#?}", values),
ActionOutcome::Trapped { message } => println!("Trap from within function: {}", message),
return result;
}

// A Rust function that does the same thing as the WASM demo, for benchmarking use.
pub fn native_add(a: i32) -> i32 {
a + 7
}

// Performance benchmarking for the demo.
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;

// Baseline benchmark: Simple Rust adition.
#[bench]
fn bench_native_add(b: &mut Bencher) {
b.iter(|| native_add(5));
}

// Benchmark: WASM addition from start to finish, including
// loading/instantiating WASM.
#[bench]
fn bench_wasm_add_unloaded(b: &mut Bencher) {
b.iter(|| wasm_add_full());
}

// Benchmark: WASM addition once everything is set up.
#[bench]
fn bench_wasm_add_loaded(b: &mut Bencher) {
let mut binary_file = File::open(concat!(env!("OUT_DIR"), "/add.wasm")).unwrap();
let mut binary: Vec<u8> = Vec::new();
binary_file.read_to_end(&mut binary).unwrap();

// In order to run this binary, we need to prepare a few inputs.

// First, we need a Wasmtime context. To build one, we need to get an ISA
// from `cranelift_native.
let isa_builder = cranelift_native::builder().unwrap();
let flag_builder = settings::builder();
let isa = isa_builder.finish(settings::Flags::new(flag_builder));

// Then, we use the ISA to build the context.
let mut context = Context::with_isa(isa);

// Now, we instantiate the WASM module loaded into memory.
let mut instance = context.instantiate_module(None, &binary).unwrap();

// And, finally, invoke our function and print the results.
// For this demo, all we're doing is adding 5 and 7 together.
let args = [RuntimeValue::I32(5), RuntimeValue::I32(7)];
b.iter(|| context.invoke(&mut instance, "add", &args));
}
println!("Done.");
}

0 comments on commit a8aa10b

Please sign in to comment.