Skip to content

Commit d5b7da5

Browse files
committed
fix: divan walltime metric
1 parent 5caa771 commit d5b7da5

File tree

4 files changed

+95
-5
lines changed

4 files changed

+95
-5
lines changed

crates/codspeed/src/walltime.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ impl RawWallTimeData {
2626
uri: String,
2727
iter_per_round: u32,
2828
max_time_ns: Option<u128>,
29-
times_ns: Vec<u128>,
29+
avg_round_times_ns: Vec<u128>,
3030
) -> Self {
3131
RawWallTimeData {
3232
metadata: BenchmarkMetadata { name, uri },
3333
iter_per_round,
3434
max_time_ns,
35-
times_ns,
35+
times_ns: avg_round_times_ns,
3636
}
3737
}
3838

@@ -50,13 +50,39 @@ impl RawWallTimeData {
5050
/// Entry point called in patched integration to harvest raw walltime data
5151
///
5252
/// `CODSPEED_CARGO_WORKSPACE_ROOT` is expected to be set for this to work
53+
///
54+
/// # Arguments
55+
///
56+
/// - `scope`: The used integration, e.g. "divan" or "criterion"
57+
/// - `name`: The name of the benchmark
58+
/// - `uri`: The URI of the benchmark
59+
/// - `iter_per_round`: The number of iterations per round for the benchmark (=sample_size)
60+
/// - `max_time_ns`: The time limit for the benchmark in nanoseconds (if defined)
61+
/// - `avg_round_times_ns`: The **average** time per iteration in nanoseconds. Calculated as `total_round_time_ns / iter_per_round`
62+
///
63+
/// # Terminology
64+
///
65+
/// - `sample_count`: The number of times the benchmark was executed.
66+
/// - `sample_size` (=iter_per_round/iterations): The number of iterations within each round.
67+
///
68+
/// ```
69+
/// for round in 0..sample_count {
70+
/// let total_round_time_ns = 0;
71+
/// for iteration in 0..iter_per_round {
72+
/// run_benchmark();
73+
/// total_round_time_ns += /* measured execution time */;
74+
/// }
75+
/// let avg_round_times_ns = total_round_time_ns / iter_per_round;
76+
/// }
77+
/// ```
78+
///
5379
pub fn collect_raw_walltime_results(
5480
scope: &str,
5581
name: String,
5682
uri: String,
5783
iter_per_round: u32,
5884
max_time_ns: Option<u128>,
59-
times_ns: Vec<u128>,
85+
avg_round_times_ns: Vec<u128>,
6086
) {
6187
if !crate::utils::running_with_codspeed_runner() {
6288
return;
@@ -66,7 +92,13 @@ pub fn collect_raw_walltime_results(
6692
eprintln!("codspeed failed to get workspace root. skipping");
6793
return;
6894
};
69-
let data = RawWallTimeData::from_runtime_data(name, uri, iter_per_round, max_time_ns, times_ns);
95+
let data = RawWallTimeData::from_runtime_data(
96+
name,
97+
uri,
98+
iter_per_round,
99+
max_time_ns,
100+
avg_round_times_ns,
101+
);
70102
data.dump_to_results(&workspace_root, scope);
71103
}
72104

crates/divan_compat/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ codspeed-divan-compat-macros = { version = "=2.10.1", path = './macros' }
2525
[[bench]]
2626
name = "basic_example"
2727
harness = false
28+
29+
[[bench]]
30+
name = "sleep_benches"
31+
harness = false
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#[divan::bench]
2+
fn sleep_1ns() {
3+
std::thread::sleep(std::time::Duration::from_nanos(1));
4+
}
5+
6+
#[divan::bench]
7+
fn sleep_100ns() {
8+
std::thread::sleep(std::time::Duration::from_nanos(100));
9+
}
10+
11+
#[divan::bench]
12+
fn sleep_1us() {
13+
std::thread::sleep(std::time::Duration::from_micros(1));
14+
}
15+
16+
#[divan::bench]
17+
fn sleep_100us() {
18+
std::thread::sleep(std::time::Duration::from_micros(100));
19+
}
20+
21+
#[divan::bench]
22+
fn sleep_1ms() {
23+
std::thread::sleep(std::time::Duration::from_millis(1));
24+
}
25+
26+
#[divan::bench]
27+
fn sleep_10ms() {
28+
std::thread::sleep(std::time::Duration::from_millis(10));
29+
}
30+
31+
#[divan::bench]
32+
fn sleep_50ms() {
33+
std::thread::sleep(std::time::Duration::from_millis(50));
34+
}
35+
36+
#[divan::bench]
37+
fn sleep_100ms() {
38+
std::thread::sleep(std::time::Duration::from_millis(100));
39+
}
40+
41+
// Tests COD-1044, do not modify the sample size or count!
42+
#[divan::bench(sample_size = 3, sample_count = 6)]
43+
fn sleep_100ms_with_custom_sample() {
44+
std::thread::sleep(std::time::Duration::from_millis(100));
45+
}
46+
47+
fn main() {
48+
codspeed_divan_compat::main();
49+
}

crates/divan_compat/divan_fork/src/divan.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,13 @@ mod codspeed {
424424
};
425425

426426
let iter_per_round = bench_context.samples.sample_size;
427+
428+
// Note: times_ns = total time of the round execution, but we need the time per iteration.
429+
// See: BenchContext::compute_stats in bench/mod.rs
427430
let times_ns: Vec<_> =
428431
bench_context.samples.time_samples.iter().map(|s| s.duration.picos / 1_000).collect();
432+
let avg_times_ns: Vec<_> = times_ns.iter().map(|&t| t / iter_per_round as u128).collect();
433+
429434
let max_time_ns = bench_context.options.max_time.map(|t| t.as_nanos());
430435

431436
if let Err(error) = ::codspeed::fifo::send_cmd(codspeed::fifo::Command::CurrentBenchmark {
@@ -443,7 +448,7 @@ mod codspeed {
443448
uri,
444449
iter_per_round,
445450
max_time_ns,
446-
times_ns,
451+
avg_times_ns,
447452
);
448453
}
449454
}

0 commit comments

Comments
 (0)