use criterion::{Criterion, criterion_group, criterion_main};
use futures::future::join_all;
use resolved::{OwnedScript, PooledResolve, Resolve, ResolveConfig, Script};
use std::{sync::Arc, time::Duration};
const NOOP: &str = "";
const SLEEP: &str = "sleep(10)";
const LENGTHY: &str = r#"
local a = 57 + 12
local b = a + 41
local c = "aaaa" .. "bbbb"
local d = a * b
local e = c .. "cccc"
function add(a, b)
return a + b
end
local f = add(5, 1)
"#;
async fn run_n<'s>(resolve: &Resolve, n: usize, script: impl Into<Script<'s>>) {
let script = script.into();
for _ in 0..n {
resolve.execute::<()>(script.clone()).await.unwrap();
}
}
async fn pool_n<'c>(pool: &PooledResolve, n: usize, script: impl Into<OwnedScript>) {
let mut handles = Vec::with_capacity(n);
let script = Arc::new(script.into());
for _ in 0..n {
let p = pool.clone();
let script = script.clone();
handles.push(tokio::spawn(async move {
p.execute::<()>(script.as_ref()).await.unwrap()
}));
}
join_all(handles).await;
}
const BENCHMARK_TIMEOUT: Duration = Duration::from_mins(5);
fn benchmark_config() -> ResolveConfig {
ResolveConfig {
timeout: BENCHMARK_TIMEOUT,
reset_globals: false,
..Default::default()
}
}
fn criterion_benchmark(c: &mut Criterion) {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.name("benchmark")
.build()
.unwrap();
let resolve =
rt.block_on(async { Resolve::new_with_config(&benchmark_config()).await.unwrap() });
let pool_2 = rt.block_on(async {
PooledResolve::new_with_config(2, benchmark_config())
.await
.unwrap()
});
let pool_8 = rt.block_on(async {
PooledResolve::new_with_config(8, benchmark_config())
.await
.unwrap()
});
let mut exec = c.benchmark_group("execute");
exec.bench_function("single_1", |b| {
b.to_async(&rt).iter(|| run_n(&resolve, 1, NOOP));
});
exec.bench_function("single_64", |b| {
b.to_async(&rt).iter(|| run_n(&resolve, 64, NOOP));
});
exec.bench_function("pool2_1", |b| {
b.to_async(&rt).iter(|| pool_n(&pool_2, 1, NOOP));
});
exec.bench_function("pool2_64", |b| {
b.to_async(&rt).iter(|| pool_n(&pool_2, 64, NOOP));
});
exec.bench_function("pool8_1", |b| {
b.to_async(&rt).iter(|| pool_n(&pool_8, 1, NOOP));
});
exec.bench_function("pool8_64", |b| {
b.to_async(&rt).iter(|| pool_n(&pool_8, 64, NOOP));
});
exec.finish();
let resolve =
rt.block_on(async { Resolve::new_with_config(&benchmark_config()).await.unwrap() });
let mut exec_lengthy = c.benchmark_group("execute_lengthy");
exec_lengthy.bench_function("single_1", |b| {
b.to_async(&rt).iter(|| run_n(&resolve, 1, LENGTHY));
});
exec_lengthy.bench_function("single_64", |b| {
b.to_async(&rt).iter(|| run_n(&resolve, 64, LENGTHY));
});
exec_lengthy.finish();
let mut work = c.benchmark_group("work");
work.bench_function("single_1", |b| {
b.to_async(&rt).iter(|| run_n(&resolve, 1, SLEEP));
});
work.bench_function("single_64", |b| {
b.to_async(&rt).iter(|| run_n(&resolve, 64, SLEEP));
});
work.bench_function("pool2_1", |b| {
b.to_async(&rt).iter(|| pool_n(&pool_2, 1, SLEEP));
});
work.bench_function("pool2_64", |b| {
b.to_async(&rt).iter(|| pool_n(&pool_2, 64, SLEEP));
});
work.bench_function("pool8_1", |b| {
b.to_async(&rt).iter(|| pool_n(&pool_8, 1, SLEEP));
});
work.bench_function("pool8_64", |b| {
b.to_async(&rt).iter(|| pool_n(&pool_8, 64, SLEEP));
});
work.finish();
let mut create = c.benchmark_group("create");
create.sample_size(50);
create.bench_function("resolve", |b| {
b.to_async(&rt).iter(|| async {
let r = Resolve::new_with_config(&benchmark_config()).await.unwrap();
std::hint::black_box(r);
});
});
create.finish();
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);