use std::fmt::Write;
use std::hint::black_box;
use askama_parser::{Ast, Syntax};
use criterion::{Criterion, Throughput, criterion_group, criterion_main};
use rand::SeedableRng;
use rand::seq::SliceRandom;
use rand_xoshiro::Xoroshiro64StarStar;
criterion_main!(benches);
criterion_group!(benches, binary_ops);
fn binary_ops(c: &mut Criterion) {
let mut rng = Xoroshiro64StarStar::seed_from_u64(PRIME64);
for (group_name, ops) in [
("range ops", ["..", "..="].as_slice()),
("mult ops", ["*", "/", "%"].as_slice()),
("mixed ops", BINARY_OPS),
] {
let mut ops = ops.to_owned();
let mut iter = std::slice::Iter::default();
let mut g = c.benchmark_group(group_name);
for count in [1, 10, 100] {
let mut source = format!("{group_name}: {{ v0");
for i in 1..=count {
let op = if let Some(&op) = iter.next() {
op
} else {
ops.shuffle(&mut rng);
iter = ops.iter();
iter.next().unwrap()
};
write!(source, " {op} v{i}").unwrap();
}
source.push_str(" }}.");
let source = source.as_str();
g.throughput(Throughput::ElementsAndBytes {
elements: count as u64,
bytes: source.len() as u64,
});
g.bench_function(format!("x{count}"), |b| {
let syntax = &Syntax::default();
b.iter(|| Ast::from_str(black_box(source), None, black_box(syntax)).unwrap());
});
}
g.finish();
}
}
const BINARY_OPS: &[&str] = &[
"..", "..=", "||", "&&", "bitor", "xor", "bitand", ">>", "<<", "+", "-", "~", "*", "/", "%",
];
const PRIME64: u64 = 0xaaaaaaaaaaaaaa3f;