aboutsummaryrefslogtreecommitdiff
path: root/primrose/crates/candelabra-benchmarker/src/indexable.rs
blob: 066ad8ae37fe646335ff548257cf69d8d6cf497e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use std::{any::type_name, collections::HashMap};

use log::debug;
use primrose_library::traits::{Container, Indexable};
use rand::{distributions::Standard, prelude::Distribution, random};

use crate::{benchmark_op, BenchmarkResult, Observation, Results};

/// Benchmark [`primrose_library::traits::Indexable`] operations
pub trait IndexableExt<E> {
    /// Benchmark at a single `n`.
    fn benchmark_indexable_at(n: usize) -> Results;

    /// Benchmark `first` at a single `n`.
    fn benchmark_indexable_first(n: usize) -> Observation;

    /// Benchmark `last` at a single `n`.
    fn benchmark_indexable_last(n: usize) -> Observation;

    /// Benchmark `nth` at a single `n`.
    fn benchmark_indexable_nth(n: usize) -> Observation;
}

impl<T, E> IndexableExt<E> for T
where
    T: Container<E> + Indexable<E> + Default,
    Standard: Distribution<E>,
{
    fn benchmark_indexable_at(n: usize) -> Results {
        let mut by_op = HashMap::new();

        debug!("Benchmarking {} at n = {}", type_name::<T>(), n);

        debug!("...first");
        by_op.insert(
            "first".to_string(),
            vec![Self::benchmark_indexable_first(n)],
        );
        debug!("...last");
        by_op.insert("last".to_string(), vec![Self::benchmark_indexable_last(n)]);
        debug!("...nth");
        by_op.insert("nth".to_string(), vec![Self::benchmark_indexable_nth(n)]);
        debug!("--- done!");

        Results { by_op }
    }

    fn benchmark_indexable_first(n: usize) -> Observation {
        (
            n,
            benchmark_op(
                || {
                    let mut c = T::default();
                    for _ in 0..n {
                        c.insert(random());
                    }
                    c
                },
                |c| {
                    c.first();
                },
                |_| (),
            ),
        )
    }

    fn benchmark_indexable_last(n: usize) -> Observation {
        (
            n,
            benchmark_op(
                || {
                    let mut c = T::default();
                    for _ in 0..n {
                        c.insert(random());
                    }
                    c
                },
                |c| {
                    c.last();
                },
                |_| (),
            ),
        )
    }

    fn benchmark_indexable_nth(n: usize) -> Observation {
        (
            n,
            benchmark_op(
                || {
                    let mut c = T::default();
                    for _ in 0..n {
                        c.insert(random());
                    }
                    (c, random::<usize>())
                },
                |(c, fetch)| {
                    c.nth(*fetch);
                },
                |_| (),
            ),
        )
    }
}