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
//! Measurement of call time using rounds with an linearly-increasing size.

use std::marker::PhantomData;

use ::Sample;
use benchmark::Benchmark;
use black_box::black_box;
use runner::{Round, Runner};
use timer::Timer;


/// Default number of executions in first round.
pub const DEFAULT_ROUND_SIZE_START: usize = 1_000;

/// Default increase in round size between rounds.
pub const DEFAULT_ROUND_SIZE_STEP: usize = 100;

/// Defualt total number of rounds to record.
pub const DEFAULT_SAMPLE_SIZE: usize = 100;

/// Run a target in linearly-increasing round sizes. These can then be analyzed
/// with, for example, linear regression.
pub struct LinearRunner<T: Timer> {
    round_size_start: usize,
    round_size_step: usize,
    sample_size: usize,
    _timer: PhantomData<T>,
}

impl<T: Timer> LinearRunner<T> {
    /// Construct a `LinearRunner`, which records a total of `sample_size`
    /// rounds. The first round records the timing of `round_size_start`
    /// executions of the target. Each subsequent round inclues an additional
    /// `round_size_step` executions.
    pub fn new(
        round_size_start: usize,
        round_size_step: usize,
        sample_size: usize,
    ) -> Self {
        LinearRunner {
            round_size_start,
            round_size_step,
            sample_size,
            _timer: PhantomData,
        }
    }

    fn run_round<B, Ret>(&mut self, round_size: usize, bench: &mut B) -> f64
    where
        B: Benchmark<Ret>,
    {

        let mut start = T::new_timer();
        let mut end = T::new_timer();

        start.mark();
        for _ in 0..round_size {
            black_box(bench.target());
        }
        end.mark();

        end.since(&start)
    }
}

impl<T: Timer> Runner<Round> for LinearRunner<T> {
    fn run<B, Ret>(&mut self, bench: &mut B) -> Sample<Round>
    where
        B: Benchmark<Ret>,
    {

        let mut data = Vec::with_capacity(self.sample_size);

        let mut round_size = self.round_size_start;
        for _ in 0..self.sample_size {
            data.push(Round {
                ns: self.run_round(round_size, bench),
                size: round_size,
            });

            round_size += self.round_size_step;
        }

        Sample { name: bench.name(), data }
    }
}