Skip to content

Commit 6e0a2e1

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

File tree

4 files changed

+94
-5
lines changed

4 files changed

+94
-5
lines changed

crates/codspeed/src/walltime.rs

Lines changed: 35 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,38 @@ 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+
/// # Pseudo-code
64+
///
65+
/// ```
66+
/// let sample_count = /* The number of executions for the same benchmark. */
67+
/// let sample_size = iter_per_round = /* The number of iterations within each sample. */;
68+
/// for round in 0..sample_count {
69+
/// let total_round_time_ns = 0;
70+
/// for iteration in 0..iter_per_round {
71+
/// run_benchmark();
72+
/// total_round_time_ns += /* measured execution time */;
73+
/// }
74+
/// let avg_round_times_ns = total_round_time_ns / iter_per_round;
75+
/// }
76+
/// ```
77+
///
5378
pub fn collect_raw_walltime_results(
5479
scope: &str,
5580
name: String,
5681
uri: String,
5782
iter_per_round: u32,
5883
max_time_ns: Option<u128>,
59-
times_ns: Vec<u128>,
84+
avg_round_times_ns: Vec<u128>,
6085
) {
6186
if !crate::utils::running_with_codspeed_runner() {
6287
return;
@@ -66,7 +91,13 @@ pub fn collect_raw_walltime_results(
6691
eprintln!("codspeed failed to get workspace root. skipping");
6792
return;
6893
};
69-
let data = RawWallTimeData::from_runtime_data(name, uri, iter_per_round, max_time_ns, times_ns);
94+
let data = RawWallTimeData::from_runtime_data(
95+
name,
96+
uri,
97+
iter_per_round,
98+
max_time_ns,
99+
avg_round_times_ns,
100+
);
70101
data.dump_to_results(&workspace_root, scope);
71102
}
72103

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)