140 lines
4.3 KiB
Rust
140 lines
4.3 KiB
Rust
#![feature(test)]
|
|
#![feature(bench_black_box)]
|
|
#![cfg(not(tarpaulin_include))]
|
|
|
|
extern crate rand;
|
|
extern crate rand_pcg;
|
|
extern crate test;
|
|
|
|
use evalexpr::build_operator_tree;
|
|
use rand::{distributions::Uniform, seq::SliceRandom, Rng, SeedableRng};
|
|
use rand_pcg::Pcg32;
|
|
use std::{fmt::Write, hint::black_box};
|
|
use test::Bencher;
|
|
|
|
const BENCHMARK_LEN: usize = 100_000;
|
|
const EXPONENTIAL_TUPLE_ITERATIONS: usize = 12;
|
|
|
|
fn generate_expression<Gen: Rng>(len: usize, gen: &mut Gen) -> String {
|
|
let int_distribution = Uniform::new_inclusive(1, 100);
|
|
let whitespaces = vec![" ", "", "", " ", " \n", " "];
|
|
let operators = vec!["+", "-", "*", "/", "%", "^"];
|
|
let mut result = String::new();
|
|
write!(result, "{}", gen.sample(int_distribution)).unwrap();
|
|
|
|
while result.len() < len {
|
|
result.push_str(whitespaces.choose(gen).unwrap());
|
|
result.push_str(operators.choose(gen).unwrap());
|
|
result.push_str(whitespaces.choose(gen).unwrap());
|
|
write!(result, "{}", gen.sample(int_distribution)).unwrap();
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
fn generate_expression_chain<Gen: Rng>(len: usize, gen: &mut Gen) -> String {
|
|
let mut chain = generate_expression(10, gen);
|
|
while chain.len() < len {
|
|
chain.push_str("; ");
|
|
chain.push_str(&generate_expression(10, gen));
|
|
}
|
|
chain
|
|
}
|
|
|
|
fn generate_small_expressions<Gen: Rng>(len: usize, gen: &mut Gen) -> Vec<String> {
|
|
let mut result = Vec::new();
|
|
let mut result_len = 0;
|
|
while result_len < len {
|
|
let expression = generate_expression(10, gen);
|
|
result_len += expression.len();
|
|
result.push(expression);
|
|
}
|
|
result
|
|
}
|
|
|
|
fn generate_large_tuple_expression<Gen: Rng>(iterations: usize, gen: &mut Gen) -> String {
|
|
let mut result = String::from("a=(");
|
|
result.push_str(&generate_expression(0, gen));
|
|
result.push(',');
|
|
result.push_str(&generate_expression(0, gen));
|
|
result.push(')');
|
|
for _ in 0..iterations {
|
|
result.push_str(";a=(a,a)")
|
|
}
|
|
dbg!(result)
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_parse_long_expression_chains(bencher: &mut Bencher) {
|
|
let mut gen = Pcg32::seed_from_u64(0);
|
|
let long_expression_chain = generate_expression_chain(BENCHMARK_LEN, &mut gen);
|
|
|
|
bencher.iter(|| build_operator_tree(&long_expression_chain).unwrap());
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_parse_deep_expression_trees(bencher: &mut Bencher) {
|
|
let mut gen = Pcg32::seed_from_u64(15);
|
|
let deep_expression_tree = generate_expression(BENCHMARK_LEN, &mut gen);
|
|
|
|
bencher.iter(|| build_operator_tree(&deep_expression_tree).unwrap());
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_parse_many_small_expressions(bencher: &mut Bencher) {
|
|
let mut gen = Pcg32::seed_from_u64(33);
|
|
let small_expressions = generate_small_expressions(BENCHMARK_LEN, &mut gen);
|
|
|
|
bencher.iter(|| {
|
|
for expression in &small_expressions {
|
|
black_box(build_operator_tree(expression).unwrap());
|
|
}
|
|
});
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_evaluate_long_expression_chains(bencher: &mut Bencher) {
|
|
let mut gen = Pcg32::seed_from_u64(0);
|
|
let long_expression_chain =
|
|
build_operator_tree(&generate_expression_chain(BENCHMARK_LEN, &mut gen)).unwrap();
|
|
|
|
bencher.iter(|| long_expression_chain.eval().unwrap());
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_evaluate_deep_expression_trees(bencher: &mut Bencher) {
|
|
let mut gen = Pcg32::seed_from_u64(15);
|
|
let deep_expression_tree =
|
|
build_operator_tree(&generate_expression(BENCHMARK_LEN, &mut gen)).unwrap();
|
|
|
|
bencher.iter(|| deep_expression_tree.eval().unwrap());
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_evaluate_many_small_expressions(bencher: &mut Bencher) {
|
|
let mut gen = Pcg32::seed_from_u64(33);
|
|
let small_expressions: Vec<_> = generate_small_expressions(BENCHMARK_LEN, &mut gen)
|
|
.iter()
|
|
.map(|expression| build_operator_tree(expression).unwrap())
|
|
.collect();
|
|
|
|
bencher.iter(|| {
|
|
for expression in &small_expressions {
|
|
black_box(expression.eval().unwrap());
|
|
}
|
|
});
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_evaluate_large_tuple_expression(bencher: &mut Bencher) {
|
|
let mut gen = Pcg32::seed_from_u64(44);
|
|
let large_tuple_expression = build_operator_tree(&generate_large_tuple_expression(
|
|
EXPONENTIAL_TUPLE_ITERATIONS,
|
|
&mut gen,
|
|
))
|
|
.unwrap();
|
|
dbg!(&large_tuple_expression);
|
|
|
|
bencher.iter(|| large_tuple_expression.eval().unwrap());
|
|
}
|