From 717c5fabc8de843bcc17f89c01669f70271e6fe3 Mon Sep 17 00:00:00 2001 From: not-matthias Date: Thu, 8 Oct 2026 15:15:37 +0200 Subject: [PATCH 1/2] docs(cargo-codspeed): clarify BENCHNAME and --bench help The BENCHNAME help claimed a substring match on benchmark names. It is an unanchored regex forwarded to each bench binary, and the matched string differs by mode: the CodSpeed URI in simulation/memory, the framework's own name in walltime. Document that, how to use --exact, and that an empty selection still exits successfully. The --bench help now mentions it can be repeated. --- crates/cargo-codspeed/src/app.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/cargo-codspeed/src/app.rs b/crates/cargo-codspeed/src/app.rs index 841c1279..6c309a10 100644 --- a/crates/cargo-codspeed/src/app.rs +++ b/crates/cargo-codspeed/src/app.rs @@ -133,7 +133,7 @@ pub(crate) struct PackageFilters { #[derive(Args, Clone)] pub(crate) struct BenchTargetFilters { - /// Select only the specified benchmark target (all benchmark targets by default) + /// Select only the specified benchmark target; can be repeated (all benchmark targets by default) #[arg(long, help_heading = TARGET_HELP)] pub(crate) bench: Option>, } @@ -200,7 +200,16 @@ enum Commands { }, /// Run the previously built benchmarks Run { - /// If specified, only run benches containing this string in their names + /// Only run benchmarks whose name matches this unanchored regex. + /// + /// The string matched against depends on the measurement mode: + /// - **simulation/memory**: the CodSpeed URI + /// - **walltime**: the benchmark framework's own name (can be listed with `-- --list`, + /// and validated with `-- --list ''`) + /// + /// To require the whole name to match instead of a regex, pass `-- --exact`. The name format + /// still differs between modes. + #[arg(verbatim_doc_comment)] benchname: Option, #[command(flatten)] From 8d24c954d95887c728c90e44fb19797a0c07658c Mon Sep 17 00:00:00 2001 From: not-matthias Date: Thu, 8 Oct 2026 13:01:40 +0200 Subject: [PATCH 2/2] fix(criterion): send benchmark markers around iter_manual rounds --- crates/codspeed/src/instrument_hooks/mod.rs | 18 ++++++++++++++++++ .../criterion_fork/src/codspeed_iter_manual.rs | 6 +++++- .../criterion_fork/src/routine.rs | 11 +++-------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/crates/codspeed/src/instrument_hooks/mod.rs b/crates/codspeed/src/instrument_hooks/mod.rs index b77ef426..e3f93deb 100644 --- a/crates/codspeed/src/instrument_hooks/mod.rs +++ b/crates/codspeed/src/instrument_hooks/mod.rs @@ -279,6 +279,24 @@ pub use linux_impl::InstrumentHooks; #[cfg(not(use_instrument_hooks))] pub use other_impl::InstrumentHooks; +/// Sends the benchmark start marker when created and the stop marker when +/// dropped, so every exit path closes the measured region. +pub struct BenchmarkMarkers(&'static InstrumentHooks); + +impl BenchmarkMarkers { + pub fn start() -> Self { + let hooks = InstrumentHooks::instance(); + let _ = hooks.start_benchmark(); + Self(hooks) + } +} + +impl Drop for BenchmarkMarkers { + fn drop(&mut self) { + let _ = self.0.stop_benchmark(); + } +} + #[cfg(test)] mod tests { use super::InstrumentHooks; diff --git a/crates/criterion_compat/criterion_fork/src/codspeed_iter_manual.rs b/crates/criterion_compat/criterion_fork/src/codspeed_iter_manual.rs index 3e615448..ce90e11e 100644 --- a/crates/criterion_compat/criterion_fork/src/codspeed_iter_manual.rs +++ b/crates/criterion_compat/criterion_fork/src/codspeed_iter_manual.rs @@ -6,7 +6,7 @@ use std::time::{Duration, Instant}; -use codspeed::instrument_hooks::InstrumentHooks; +use codspeed::instrument_hooks::{BenchmarkMarkers, InstrumentHooks}; #[cfg(feature = "async")] use crate::async_executor::AsyncExecutor; @@ -112,6 +112,7 @@ impl<'a, M: Measurement> Bencher<'a, M> { self.elapsed_time = Duration::ZERO; let mut samples = Vec::with_capacity(opts.rounds as usize); + let markers = BenchmarkMarkers::start(); for _ in 0..opts.rounds { let bench_start = InstrumentHooks::current_timestamp(); let round_start = Instant::now(); @@ -126,6 +127,7 @@ impl<'a, M: Measurement> Bencher<'a, M> { samples.push(self.measurement.to_f64(&value)); } + drop(markers); self.codspeed_manual = Some(ManualMeasurement { samples, @@ -172,6 +174,7 @@ impl<'a, 'b, A: AsyncExecutor, M: Measurement> AsyncBencher<'a, 'b, A, M> { b.elapsed_time = Duration::ZERO; let mut samples = Vec::with_capacity(opts.rounds as usize); + let markers = BenchmarkMarkers::start(); for _ in 0..opts.rounds { let bench_start = InstrumentHooks::current_timestamp(); let round_start = Instant::now(); @@ -186,6 +189,7 @@ impl<'a, 'b, A: AsyncExecutor, M: Measurement> AsyncBencher<'a, 'b, A, M> { samples.push(b.measurement.to_f64(&value)); } + drop(markers); b.codspeed_manual = Some(ManualMeasurement { samples, diff --git a/crates/criterion_compat/criterion_fork/src/routine.rs b/crates/criterion_compat/criterion_fork/src/routine.rs index c5ffd3bd..709e5c5c 100644 --- a/crates/criterion_compat/criterion_fork/src/routine.rs +++ b/crates/criterion_compat/criterion_fork/src/routine.rs @@ -1,4 +1,4 @@ -use codspeed::instrument_hooks::InstrumentHooks; +use codspeed::instrument_hooks::BenchmarkMarkers; use crate::benchmark::BenchmarkConfig; use crate::codspeed_iter_manual::ManualMeasurement; @@ -238,13 +238,8 @@ pub(crate) trait Routine { } let m_elapsed = { - let hooks = InstrumentHooks::instance(); - - let _ = hooks.start_benchmark(); - let value = self.bench(measurement, &m_iters, parameter); - let _ = hooks.stop_benchmark(); - - value + let _markers = BenchmarkMarkers::start(); + self.bench(measurement, &m_iters, parameter) }; let m_iters_f: Vec = m_iters.iter().map(|&x| x as f64).collect();