Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clock.delta_as_nanos, a delta that skips conversion to Duration #86

Merged
merged 2 commits into from
May 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
10 changes: 10 additions & 0 deletions benches/timing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ fn time_quanta_raw_delta(b: &mut Bencher) {
})
}

fn time_quanta_raw_delta_as_nanos(b: &mut Bencher) {
let clock = Clock::new();
b.iter(|| {
let start = clock.raw();
let end = clock.raw();
clock.delta_as_nanos(start, end)
})
}

fn time_quanta_now_delta(b: &mut Bencher) {
let clock = Clock::new();
b.iter(|| {
Expand Down Expand Up @@ -75,6 +84,7 @@ fn benchmark(c: &mut Criterion) {
q_group.bench_function("quanta_raw", time_quanta_raw);
q_group.bench_function("quanta_raw_scaled", time_quanta_raw_scaled);
q_group.bench_function("quanta_raw_delta", time_quanta_raw_delta);
q_group.bench_function("quanta_raw_delta_as_nanos", time_quanta_raw_delta_as_nanos);
q_group.bench_function("quanta_recent", time_quanta_recent);
q_group.bench_function("quanta_instant_recent", time_quanta_instant_recent);
q_group.finish();
Expand Down
35 changes: 26 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,29 +388,46 @@ impl Clock {
Instant(scaled)
}

/// Calculates the delta between two measurements, and scales to reference time.
/// Calculates the delta in nanoseconds scaled to reference time in nanoseconds
/// between two measurements.
antifuchs marked this conversation as resolved.
Show resolved Hide resolved
///
/// This method is slightly faster when you know you need the delta between two raw
/// measurements, or a start/end measurement, than using [`scaled`] for both conversions.
/// This method is very similar to [`delta`] but reduces overhead
/// for high-frequency measurements that work with nanosecond
/// counts internally, as it avoids the conversion of the delta
/// into [`Duration`].
///
/// [`scaled`]: Clock::scaled
pub fn delta(&self, start: u64, end: u64) -> Duration {
/// [`delta`]: Clock::delta
pub fn delta_as_nanos(&self, start: u64, end: u64) -> u64 {
// Safety: we want wrapping_sub on the end/start delta calculation so that two measurements
// split across a rollover boundary still return the right result. However, we also know
// the TSC could potentially give us different values between cores/sockets, so we're just
// doing our due diligence here to make sure we're not about to create some wacky duration.
if end <= start {
return Duration::new(0, 0);
return 0;
}

let delta = end.wrapping_sub(start);
let scaled = match &self.inner {
match &self.inner {
ClockType::Counter(_, _, calibration) => {
mul_div_po2_u64(delta, calibration.scale_factor, calibration.scale_shift)
}
_ => delta,
};
Duration::from_nanos(scaled)
}
}

/// Calculates the delta between two measurements, and scales to reference time.
antifuchs marked this conversation as resolved.
Show resolved Hide resolved
///
/// This method is slightly faster when you know you need the delta between two raw
/// measurements, or a start/end measurement, than using [`scaled`] for both conversions.
///
/// In code that uses `clock.delta(start, end).as_nanos()` with
/// high frequency, consider [`delta_as_nanos`] instead, as that
/// avoids the round-trip conversion through [`Duration`].
antifuchs marked this conversation as resolved.
Show resolved Hide resolved
///
/// [`scaled`]: Clock::scaled
/// [`delta_as_nanos`]: Clock::delta_as_nanos
pub fn delta(&self, start: u64, end: u64) -> Duration {
Duration::from_nanos(self.delta_as_nanos(start, end))
}

/// Gets the most recent current time, scaled to reference time.
Expand Down