use std::hint::black_box;
use std::time::Duration;
fn create_output(msg: &str, i: u32) {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let result = document.create_element("div").unwrap();
result
.set_attribute("id", &format!("wasm_bench_result_{i}"))
.unwrap();
result.set_text_content(Some(msg));
let body = document.body().unwrap();
body.append_child(&result).unwrap();
}
fn mark_finished() {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let result = document.create_element("div").unwrap();
result.set_attribute("id", "wasm_bench_done").unwrap();
let body = document.body().unwrap();
body.append_child(&result).unwrap();
}
#[derive(Default)]
pub struct Bencher {
index: u32,
}
impl Bencher {
pub fn start<R: Future<Output = ()> + 'static>(inner: impl FnOnce(Self) -> R) {
wasm_bindgen_futures::spawn_local(inner(Self { index: 0 }));
}
pub async fn bench<A: Clone, R>(&mut self, name: &str, arg: A, func: impl Fn(A) -> R) {
let performance = web_sys::window().unwrap().performance().unwrap();
let start = performance.now();
let _ = func(black_box(arg.clone()));
let mut end = performance.now();
if start == end {
end += 1.0;
}
let target_iterations = 5000.0_f64.div_euclid(end - start) as u128;
let mut total_ms = 0.0;
for _ in 0..target_iterations {
let start = performance.now();
let _ = func(black_box(arg.clone()));
let end = performance.now();
total_ms += end - start;
}
let average = total_ms / target_iterations as f64;
create_output(
&format!("{name} (iters: {target_iterations}): {average:.8}ms"),
self.index,
);
self.index += 1;
gloo::timers::future::sleep(Duration::from_millis(10)).await;
}
}
impl Drop for Bencher {
fn drop(&mut self) {
mark_finished();
}
}