Skip to content

Commit 02292c7

Browse files
committed
fix(walltime): use mach_absolute_time for FIFO timestamps on macOS
Mirror the clock used elsewhere in CodSpeed on macOS (mach_absolute_time with cached mach_timebase_info) so runner and benchmark process timestamps come from the exact same source. Adds mach2 as a macOS-only dependency.
1 parent 505a703 commit 02292c7

3 files changed

Lines changed: 44 additions & 4 deletions

File tree

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ crc32fast = "1.5.0"
7878
[target.'cfg(target_os = "linux")'.dependencies]
7979
procfs = "0.17.0"
8080

81+
[target.'cfg(target_os = "macos")'.dependencies]
82+
mach2 = "0.4"
83+
8184
[dev-dependencies]
8285
temp-env = { version = "0.3.6", features = ["async_closure"] }
8386
insta = { version = "1.29.0", features = ["json", "redactions"] }

src/executor/shared/fifo.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::prelude::*;
22
use anyhow::Context;
33
use futures::StreamExt;
4-
use nix::{sys::time::TimeValLike, time::clock_gettime};
54
use runner_shared::artifacts::ExecutionTimestamps;
65
use runner_shared::fifo::{Command as FifoCommand, MarkerType};
76
use runner_shared::fifo::{RUNNER_ACK_FIFO, RUNNER_CTL_FIFO};
@@ -177,9 +176,37 @@ impl RunnerFifo {
177176
let mut integration = None;
178177

179178
let current_time = || {
180-
clock_gettime(nix::time::ClockId::CLOCK_MONOTONIC)
181-
.unwrap()
182-
.num_nanoseconds() as u64
179+
// Must match the clock used by instrument-hooks (`instrument_hooks_current_timestamp`)
180+
// so timestamps from this process and the benchmarked process are comparable.
181+
#[cfg(target_os = "macos")]
182+
{
183+
use mach2::mach_time;
184+
use std::sync::OnceLock;
185+
186+
static NANOS_PER_TICK: OnceLock<mach_time::mach_timebase_info> = OnceLock::new();
187+
188+
let nanos_per_tick = NANOS_PER_TICK.get_or_init(|| unsafe {
189+
let mut info = mach_time::mach_timebase_info::default();
190+
let errno = mach_time::mach_timebase_info(&mut info as *mut _);
191+
if errno != 0 || info.denom == 0 {
192+
info.numer = 1;
193+
info.denom = 1;
194+
};
195+
info
196+
});
197+
198+
let time = unsafe { mach_time::mach_absolute_time() };
199+
200+
time * nanos_per_tick.numer as u64 / nanos_per_tick.denom as u64
201+
}
202+
203+
#[cfg(not(target_os = "macos"))]
204+
{
205+
use nix::{sys::time::TimeValLike, time::clock_gettime};
206+
207+
let clock = nix::time::ClockId::CLOCK_MONOTONIC;
208+
clock_gettime(clock).unwrap().num_nanoseconds() as u64
209+
}
183210
};
184211

185212
let mut benchmark_started = false;

0 commit comments

Comments
 (0)