From 5b54240f9d300cd73d7507e792e5611a32cce94a Mon Sep 17 00:00:00 2001 From: Luc Varoqui Date: Thu, 22 Oct 2026 17:08:39 +0200 Subject: [PATCH] feat(codspeed): time each benchmark with round markers The runner times a benchmark when it receives the commands that start and stop it, a while before the benchmark starts and after it ends: tens of microseconds, longer than many benchmarks. Time each benchmark in the process too, right after the start command and right after the benchmarked code returns, outside of the measured section, and send these bounds as round markers before the stop command. They are sent whatever the instrumentation status: instrument hooks drops them outside of the CodSpeed runner and under Valgrind. Only the builds that run each benchmark once, under `cfg(codspeed)`, send them: the native harness also runs in walltime builds, whose rounds are the walltime loop's. Refs COD-3862 Co-Authored-By: Claude Opus 5.5 --- crates/codspeed/build.rs | 1 + crates/codspeed/src/codspeed.rs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/crates/codspeed/build.rs b/crates/codspeed/build.rs index 77f06f09..81e7850f 100644 --- a/crates/codspeed/build.rs +++ b/crates/codspeed/build.rs @@ -1,5 +1,6 @@ fn main() { println!("cargo:rustc-check-cfg=cfg(use_instrument_hooks)"); + println!("cargo:rustc-check-cfg=cfg(codspeed)"); println!("cargo:rerun-if-changed=instrument-hooks/dist/core.c"); println!("cargo:rerun-if-changed=instrument-hooks/includes/core.h"); diff --git a/crates/codspeed/src/codspeed.rs b/crates/codspeed/src/codspeed.rs index 1a4644d2..1556c241 100644 --- a/crates/codspeed/src/codspeed.rs +++ b/crates/codspeed/src/codspeed.rs @@ -30,6 +30,9 @@ pub struct CodSpeed { current_benchmark: CString, group_stack: Vec, instrumentation_status: InstrumentationStatus, + /// When the current benchmark started, on the clock of the benchmark markers. + #[cfg(codspeed)] + round_start: u64, } impl CodSpeed { @@ -67,6 +70,8 @@ impl CodSpeed { current_benchmark: CString::new("").expect("CString::new failed"), group_stack: Vec::new(), instrumentation_status, + #[cfg(codspeed)] + round_start: 0, } } @@ -87,6 +92,11 @@ impl CodSpeed { let _ = hooks_instance.start_benchmark(); } + #[cfg(codspeed)] + { + self.round_start = crate::instrument_hooks::InstrumentHooks::current_timestamp(); + } + // We intentionally do this no matter the instrumentation status. // The overhead in case we are not running valgrind is extremely low, and we do not want to // add a conditionnal branch to valgrind measurements. @@ -99,6 +109,14 @@ impl CodSpeed { // The overhead in case we are not running valgrind is extremely low, and we do not want to // add a conditionnal branch to valgrind measurements. measurement::stop(&self.current_benchmark); + + #[cfg(codspeed)] + { + let round_end = crate::instrument_hooks::InstrumentHooks::current_timestamp(); + crate::instrument_hooks::InstrumentHooks::instance() + .add_benchmark_timestamps(self.round_start, round_end); + } + if let InstrumentationStatus::InstrumentHooks(hooks_instance) = &self.instrumentation_status { let _ = hooks_instance.stop_benchmark();