cachedhash 0.3.0

Wrapper for values that caches their hash.
Documentation
use cachedhash::CachedHash;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use std::fmt::Formatter;
use std::hash::Hash;
use std::{collections::HashMap, fmt::Display};

#[inline]
fn move_things_around<T: Hash + Eq>(
    map1: &mut HashMap<T, ()>,
    map2: &mut HashMap<T, ()>,
    steps: usize,
) {
    for _ in 0..steps {
        for (key, value) in map1.drain() {
            map2.insert(key, value);
        }
        for (key, value) in map2.drain() {
            map1.insert(key, value);
        }
    }
}

struct Param(usize, usize, usize);

impl Display for Param {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} {} {}", self.0, self.1, self.2)
    }
}

fn bench(c: &mut Criterion) {
    let mut group = c.benchmark_group("A");
    for &map_size in [100, 1000, 10000].iter() {
        for &word_length in [5, 10, 20, 100].iter() {
            for &steps in [1, 5, 10, 20].iter() {
                let mut data = vec![];
                for j in 0..map_size {
                    data.push(j.to_string().repeat(word_length));
                }
                bench_hashmap("Regular", &mut group, map_size, word_length, steps, &data);
                let data = data.into_iter().map(CachedHash::new).collect::<Vec<_>>();
                bench_hashmap("Cached", &mut group, map_size, word_length, steps, &data);
            }
        }
    }
    group.finish();
}

fn bench_hashmap<T: Eq + Hash + Clone>(
    name: &str,
    group: &mut criterion::BenchmarkGroup<criterion::measurement::WallTime>,
    map_size: usize,
    word_length: usize,
    steps: usize,
    data: &Vec<T>,
) {
    group.bench_with_input(
        BenchmarkId::new(name, Param(map_size, word_length, steps)),
        data,
        |b, data| {
            b.iter(|| {
                let mut map = HashMap::new();
                for key in data {
                    map.insert(key.clone(), ());
                }
                move_things_around(&mut map, &mut HashMap::new(), steps);
            })
        },
    );
}

criterion_group!(benches, bench);
criterion_main!(benches);