Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions crates/codspeed/src/compat_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::codspeed::CodSpeed;
use crate::instrument_hooks::InstrumentHooks;
use std::time::{Duration, Instant};

/// Runs multiple rounds of a benchmark based on CODSPEED_RUNNER_MODE.
///
/// # Important
/// `start_benchmark()` and `end_benchmark()` are called on the OUTSIDE because they
/// clear CPU caches. This is expensive and should only happen once per benchmark.
/// Inside the loop, we use `toggle_collect()` to pause/resume data collection
/// between iterations without clearing caches.
///
/// # Arguments
/// * `codspeed` - The CodSpeed instance to use for benchmarking
/// * `uri` - The benchmark identifier/URI
/// * `run_iteration` - Closure that runs a single benchmark iteration.
/// Should call `toggle_collect()` to resume/pause collection
/// around the measured code.
pub fn run_rounds(codspeed: &mut CodSpeed, uri: &str, mut run_iteration: impl FnMut()) {
let (max_rounds, max_duration) = match std::env::var("CODSPEED_RUNNER_MODE").as_deref() {
Ok("simulation") | Ok("instrumentation") => (None, Some(Duration::from_millis(100))),
Ok("memory") => (Some(1), None),
Ok(m) => unreachable!("Invalid runner mode: {m}"),
Err(err) => panic!("Failed to get runner mode: {err}"),
};

let mut rounds = 0;
let rounds_start_time = Instant::now();

// Start benchmark ONCE - this clears CPU caches
codspeed.start_benchmark(uri);
InstrumentHooks::toggle_collect(); // Pause collection before first iteration

loop {
rounds += 1;

run_iteration();

let within_rounds = max_rounds.map_or(true, |max| rounds < max);
let within_duration = max_duration.map_or(true, |max| rounds_start_time.elapsed() < max);

if !(within_rounds && within_duration) {
break;
}
}

// End benchmark ONCE
codspeed.end_benchmark();
}
11 changes: 10 additions & 1 deletion crates/codspeed/src/instrument_hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ mod ffi;

#[cfg(use_instrument_hooks)]
mod linux_impl {

use super::ffi;
use crate::measurement;
use std::ffi::CString;
use std::sync::OnceLock;

Expand Down Expand Up @@ -44,6 +44,12 @@ mod linux_impl {
unsafe { ffi::instrument_hooks_is_instrumented(self.0) }
}

// FIXME: Should we move this to instrument-hooks native library?
#[inline(always)]
pub fn toggle_collect() {
measurement::toggle_collect();
}

#[inline(always)]
pub fn start_benchmark(&self) -> Result<(), u8> {
let result = unsafe { ffi::instrument_hooks_start_benchmark(self.0) };
Expand Down Expand Up @@ -165,6 +171,9 @@ mod other_impl {
false
}

#[inline(always)]
pub fn toggle_collect() {}

pub fn start_benchmark(&self) -> Result<(), u8> {
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions crates/codspeed/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod codspeed;
pub mod compat_utils;

pub mod instrument_hooks;

Expand Down
5 changes: 5 additions & 0 deletions crates/codspeed/src/measurement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ pub fn set_metadata() {
}
}

#[inline(always)]
pub fn toggle_collect() {
unsafe { send_client_request(0, &[ClientRequest::ToggleCollect as Value, 0, 0, 0, 0, 0]) };
}

#[inline(always)]
pub fn start() {
unsafe {
Expand Down
1 change: 1 addition & 0 deletions crates/codspeed/src/request/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const CG_BASE: u32 = ((b'C' as u32) << 24) + ((b'T' as u32) << 16);
pub enum ClientRequest {
RunningOnValgrind = 0x1001,
ZeroStatistics = CG_BASE + 1,
ToggleCollect = CG_BASE + 2,
DumpStatisticsAt = CG_BASE + 3,
StartInstrumentation = CG_BASE + 4,
StopInstrumentation = CG_BASE + 5,
Expand Down
Loading
Loading