use std::{collections::HashMap, hash::Hash, hint::black_box};
use criterion::{Criterion, criterion_group, criterion_main};
use enum_table::{EnumTable, Enumerable};
#[derive(Clone, Copy, Enumerable, Eq, PartialEq, Hash)]
enum Letter {
A,
B,
C,
D,
E,
F,
G,
}
const LEN: usize = Letter::COUNT;
fn value_for(letter: Letter) -> &'static str {
match letter {
Letter::A => "Alpha",
Letter::B => "Bravo",
Letter::C => "Charlie",
Letter::D => "Delta",
Letter::E => "Echo",
Letter::F => "Foxtrot",
Letter::G => "Golf",
}
}
fn new_table() -> EnumTable<Letter, &'static str, LEN> {
EnumTable::from_fn(value_for)
}
fn new_hash_map() -> HashMap<Letter, &'static str> {
Letter::VARIANTS
.iter()
.map(|l| (*l, value_for(*l)))
.collect()
}
fn construction(c: &mut Criterion) {
let mut group = c.benchmark_group("construction");
group.bench_function("EnumTable::from_fn", |b| b.iter(|| black_box(new_table())));
group.bench_function("HashMap (new + insert all)", |b| {
b.iter(|| black_box(new_hash_map()))
});
group.finish();
}
fn single_get(c: &mut Criterion) {
let table = new_table();
let map = new_hash_map();
let mut group = c.benchmark_group("single_get");
group.bench_function("EnumTable::get", |b| {
b.iter(|| black_box(*black_box(&table).get(black_box(Letter::D))))
});
group.bench_function("EnumTable::get_const", |b| {
b.iter(|| black_box(*black_box(&table).get_const(black_box(Letter::D))))
});
group.bench_function("HashMap::get", |b| {
b.iter(|| {
if let Some(v) = black_box(&map).get(black_box(&Letter::D)) {
black_box(*v);
}
})
});
group.finish();
}
fn single_set(c: &mut Criterion) {
let mut table = new_table();
let mut map = new_hash_map();
let mut group = c.benchmark_group("single_set");
group.bench_function("EnumTable::set", |b| {
b.iter(|| black_box(table.set(black_box(Letter::D), black_box("Updated"))))
});
group.bench_function("HashMap::insert", |b| {
b.iter(|| black_box(map.insert(black_box(Letter::D), black_box("Updated"))))
});
group.finish();
}
fn bulk_get_all_variants(c: &mut Criterion) {
let table = new_table();
let map = new_hash_map();
let mut group = c.benchmark_group("bulk_get_all_variants");
group.bench_function("EnumTable::get", |b| {
b.iter(|| {
for letter in Letter::VARIANTS {
black_box(*black_box(&table).get(black_box(*letter)));
}
})
});
group.bench_function("HashMap::get", |b| {
b.iter(|| {
for letter in Letter::VARIANTS {
if let Some(v) = black_box(&map).get(black_box(letter)) {
black_box(*v);
}
}
})
});
group.finish();
}
fn bulk_set_all_variants(c: &mut Criterion) {
let mut table = new_table();
let mut map = new_hash_map();
let mut group = c.benchmark_group("bulk_set_all_variants");
group.bench_function("EnumTable::set", |b| {
b.iter(|| {
for letter in Letter::VARIANTS {
black_box(table.set(black_box(*letter), black_box("Updated")));
}
})
});
group.bench_function("HashMap::insert", |b| {
b.iter(|| {
for letter in Letter::VARIANTS {
black_box(map.insert(black_box(*letter), black_box("Updated")));
}
})
});
group.finish();
}
fn iteration(c: &mut Criterion) {
let table = new_table();
let map = new_hash_map();
let mut group = c.benchmark_group("iteration");
group.bench_function("EnumTable::iter", |b| {
b.iter(|| {
black_box(
black_box(&table)
.iter()
.map(|(_, v)| v.len())
.sum::<usize>(),
)
})
});
group.bench_function("HashMap::iter", |b| {
b.iter(|| black_box(map.values().map(|v| v.len()).sum::<usize>()))
});
group.finish();
}
criterion_group!(
benches,
construction,
single_get,
single_set,
bulk_get_all_variants,
bulk_set_all_variants,
iteration,
);
criterion_main!(benches);