wgpu_benchmark/
iter.rs

1use std::time::Duration;
2
3use crate::{BenchmarkContext, LoopControl, SubBenchResult};
4
5pub fn iter(
6    ctx: &BenchmarkContext,
7    name: &str,
8    throughput_unit: &str,
9    throughput_count_per_iteration: u32,
10    mut f: impl FnMut() -> Duration,
11) -> SubBenchResult {
12    profiling::scope!("iter", name);
13
14    let mut iterations = 0_u32;
15    let mut duration = Duration::ZERO;
16
17    let control = if let Some(override_control) = ctx.override_iters {
18        override_control
19    } else {
20        ctx.default_iterations
21    };
22
23    while !control.finished(iterations, duration) {
24        duration += f();
25        iterations += 1;
26    }
27
28    SubBenchResult {
29        name: name.to_string(),
30        avg_duration_per_iteration: duration / iterations,
31        iterations,
32        throughput_unit: throughput_unit.to_string(),
33        throughput_count_per_iteration,
34    }
35}
36
37pub fn iter_auto(
38    ctx: &BenchmarkContext,
39    name: &str,
40    throughput_unit: &str,
41    throughput_count_per_iteration: u32,
42    mut f: impl FnMut(),
43) -> SubBenchResult {
44    iter(
45        ctx,
46        name,
47        throughput_unit,
48        throughput_count_per_iteration,
49        || {
50            let start = std::time::Instant::now();
51            f();
52            start.elapsed()
53        },
54    )
55}
56
57pub fn iter_many(
58    ctx: &BenchmarkContext,
59    names: Vec<String>,
60    throughput_unit: &str,
61    throughput_count_per_iteration: u32,
62    mut f: impl FnMut() -> Vec<Duration>,
63) -> Vec<SubBenchResult> {
64    profiling::scope!("iter", &*names[0]);
65
66    let mut iterations = 0_u32;
67    let mut durations = vec![Duration::ZERO; names.len()];
68
69    let control = if let Some(override_control) = ctx.override_iters {
70        override_control
71    } else {
72        LoopControl::Time(Duration::from_secs(1))
73    };
74
75    // We use the first duration to determine whether to stop. This means the other sub-benchmarks
76    // could have run for longer or shorter than intended, but that's acceptable.
77    while !control.finished(iterations, *durations.first().unwrap_or(&Duration::ZERO)) {
78        let iteration_durations = f();
79        assert_eq!(iteration_durations.len(), names.len());
80        for (i, dur) in iteration_durations.into_iter().enumerate() {
81            durations[i] += dur;
82        }
83        iterations += 1;
84    }
85
86    durations
87        .into_iter()
88        .enumerate()
89        .map(|(i, d)| SubBenchResult {
90            name: names[i].to_string(),
91            avg_duration_per_iteration: d / iterations,
92            iterations,
93            throughput_unit: throughput_unit.to_string(),
94            throughput_count_per_iteration,
95        })
96        .collect()
97}