use std::fs::read;
use std::time::{Duration, Instant};
use futures::future::try_join_all;
use wapc::{errors, WapcHost};
use wapc_codec::messagepack::{deserialize, serialize};
use wapc_pool::HostPoolBuilder;
#[test_log::test(tokio::test)]
async fn benchmark() -> Result<(), errors::Error> {
let buf = read("../../wasm/crates/wapc-guest-test/build/wapc_guest_test.wasm")?;
let num_threads: u32 = 10;
let num_calls: u32 = 100;
let engine = wasmtime_provider::WasmtimeEngineProviderBuilder::new()
.module_bytes(&buf)
.build()?;
let pool = HostPoolBuilder::new()
.name("wasmtime-test")
.factory(move || {
let engine = engine.clone();
WapcHost::new(Box::new(engine), None).unwrap()
})
.min_threads(num_threads as _)
.max_threads(num_threads as _)
.build();
println!("Waiting for threads to spin up");
std::thread::sleep(Duration::from_millis(3000));
let hello = "hello world".to_owned();
println!("Priming WASM engines");
let priming_futs = (0..num_threads).map(|_| pool.call("echo", serialize(&hello).unwrap()));
futures::future::join_all(priming_futs).await;
println!("Priming finished");
let now = Instant::now();
let callresult = pool.call("echo", serialize(&hello).unwrap()).await?;
let base_duration = now.elapsed();
println!("Base duration of one call is {}μs", base_duration.as_micros());
let result: String = deserialize(&callresult).unwrap();
assert_eq!(result, "hello world");
let now = Instant::now();
let result =
try_join_all((0..num_calls).map(|num| pool.call("echo", serialize(&format!("hello world: {}", num)).unwrap())))
.await;
let duration_all = now.elapsed();
println!(
"{} calls across {} threads took {}μs",
num_calls,
num_threads,
duration_all.as_micros()
);
let per_thread_margin = 75;
let buffer = Duration::from_micros((per_thread_margin * (num_calls / num_threads)) as _);
let expected_max = base_duration * (num_calls / num_threads);
assert!(result.is_ok());
let returns = result.unwrap();
for (i, bytes) in returns.iter().enumerate() {
let result: String = deserialize(bytes).unwrap();
assert_eq!(result, format!("hello world: {}", i));
}
println!(
"Expecting {} calls to take around {}μs - {}μs",
num_calls,
expected_max.as_micros(),
(expected_max + buffer).as_micros()
);
Ok(())
}