Using hashmap seems to give a decent speedup overall.
hello outpath time: [528.01 ms 529.17 ms 530.64 ms]
change: [-22.932% -22.563% -22.181%] (p = 0.00 < 0.05)
Performance has improved.
firefox outpath time: [4.7647 s 4.8149 s 4.8917 s]
change: [-21.251% -20.408% -18.914%] (p = 0.00 < 0.05)
Performance has improved.
But it slows down derivation parsing by about 1-1.5%
Added another attr merge benchmark that helped me while profiling,
not sure if we want to keep that.
Change-Id: Icb9f1e2d40bbb7150af1b8df192bf3c860bae79b
Reviewed-on: https://cl.snix.dev/c/snix/+/30309
Tested-by: besadii
Reviewed-by: Florian Klink <flokli@flokli.de>
108 lines
2.9 KiB
Rust
108 lines
2.9 KiB
Rust
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
|
use itertools::Itertools;
|
|
use mimalloc::MiMalloc;
|
|
|
|
#[global_allocator]
|
|
static GLOBAL: MiMalloc = MiMalloc;
|
|
|
|
fn interpret(code: &str) {
|
|
snix_eval::Evaluation::builder_pure()
|
|
.build()
|
|
.evaluate(code, None);
|
|
}
|
|
|
|
fn eval_literals(c: &mut Criterion) {
|
|
c.bench_function("int", |b| {
|
|
b.iter(|| {
|
|
interpret(black_box("42"));
|
|
})
|
|
});
|
|
}
|
|
|
|
fn eval_merge_attrs(c: &mut Criterion) {
|
|
c.bench_function("merge small attrs", |b| {
|
|
b.iter(|| {
|
|
interpret(black_box("{ a = 1; b = 2; } // { c = 3; }"));
|
|
})
|
|
});
|
|
|
|
c.bench_function("merge large attrs with small attrs", |b| {
|
|
let large_attrs = format!(
|
|
"{{{}}}",
|
|
(0..10000).map(|n| format!("a{n} = {n};")).join(" ")
|
|
);
|
|
let expr = format!("{large_attrs} // {{ c = 3; }}");
|
|
b.iter(move || {
|
|
interpret(black_box(&expr));
|
|
})
|
|
});
|
|
|
|
c.bench_function("merge small attrs with large attrs", |b| {
|
|
let large_attrs = format!(
|
|
"{{{}}}",
|
|
(0..10000).map(|n| format!("a{n} = {n};")).join(" ")
|
|
);
|
|
let expr = format!("{{ c = 3 }} // {large_attrs}");
|
|
b.iter(move || {
|
|
interpret(black_box(&expr));
|
|
})
|
|
});
|
|
}
|
|
|
|
fn eval_intersect_attrs(c: &mut Criterion) {
|
|
c.bench_function("intersect small attrs", |b| {
|
|
b.iter(|| {
|
|
interpret(black_box(
|
|
"builtins.intersectAttrs { a = 1; b = 2; } { c = 3; }",
|
|
));
|
|
})
|
|
});
|
|
|
|
c.bench_function("intersect large attrs with small attrs", |b| {
|
|
let large_attrs = format!(
|
|
"{{{}}}",
|
|
(0..10000).map(|n| format!("a{n} = {n};")).join(" ")
|
|
);
|
|
let expr = format!("builtins.intersectAttrs {large_attrs} {{ c = 3; }}");
|
|
b.iter(move || {
|
|
interpret(black_box(&expr));
|
|
})
|
|
});
|
|
|
|
c.bench_function("intersect large attrs with large attrs", |b| {
|
|
// the intersection is 2n=3m, which is about ~⅓ of the union, and ~¼ of the elements < 2*1e4
|
|
|
|
let left_attrs = format!(
|
|
"{{{}}}",
|
|
(0..10000)
|
|
.map(|n| {
|
|
let i = 2 * n;
|
|
format!("a{i} = {i};")
|
|
})
|
|
.join(" ")
|
|
);
|
|
|
|
let right_attrs = format!(
|
|
"{{{}}}",
|
|
(0..10000)
|
|
.map(|m| {
|
|
let j = 3 * m;
|
|
format!("a{j} = {j};")
|
|
})
|
|
.join(" ")
|
|
);
|
|
|
|
let expr = format!("builtins.intersectAttrs {left_attrs} {right_attrs}");
|
|
b.iter(move || {
|
|
interpret(black_box(&expr));
|
|
})
|
|
});
|
|
}
|
|
|
|
criterion_group!(
|
|
benches,
|
|
eval_literals,
|
|
eval_merge_attrs,
|
|
eval_intersect_attrs
|
|
);
|
|
criterion_main!(benches);
|