Hardware-based tick counters for high-precision benchmarks

crates.io docs build & test license

x86_64: executes RDTSC CPU instruction to read the time-stamp counter.

AArch64: reads value of the CNTVCT_EL0 counter-timer register.

Tested on platforms

text x86_64 (Intel® Core™ i7) AArch64 (Apple M1 Pro)

Usage

For usage samples please look at src/bin/sample.rs

Basic usage

rust let start = tick_counter::start(); // ... lines of code to benchmark let elapsed_ticks = tick_counter::stop() - start; println!("Number of elapsed ticks: {}", elapsed_ticks);

Basic usage with helper

```rust use tick_counter::TickCounter;

let tickcounter = TickCounter::current(); // ... lines of code to benchmark let elapsedticks = tickcounter.elapsed(); println!("Number of elapsed ticks: {}", elapsedticks); ```

Extended usage

```rust use std::{thread, time, env::consts};

println!("Environment: {}/{} {}", consts::OS, consts::FAMILY, consts::ARCH);

let (counterfrequency, accuracy) = tickcounter::frequency(); println!("Tick frequency, MHZ: {}", counterfrequency as f64 / 1e6f64); let estimationsource = match accuracy { tickcounter::TickCounterFrequencyBase::Hardware => "hardware".tostring(), tickcounter::TickCounterFrequencyBase::Measured(duration) => format!("software, estimated in {:?}", duration) }; println!("Tick frequency is provided by: {}", estimation_source);

let counteraccuracy = tickcounter::precision(counterfrequency); println!("Tick accuracy, nanoseconds: {}", counteraccuracy);

let counterstart = tickcounter::start(); thread::sleep(time::Duration::fromsecs(1)); let counterstop = tick_counter::stop();

println!("Tick counter start: {}", counterstart); println!("Tick counter stop: {}", counterstop);

let elapsedticks = counterstop - counterstart; println!("Elapsed ticks count in ~1 seconds thread::sleep(): {}", elapsedticks);

let elapsednanoseconds = (elapsedticks as f64) * counteraccuracy; println!("Elapsed nanoseconds according to elapsed ticks: {}", elapsednanoseconds); ```

Outputs

1. Macbook Pro 16 2021 / Apple Silicon

text Apple M1 Pro MacOS Ventura 13.5.1, Darwin Kernel Version 22.6.0

Output

```text Basic usage:

Number of elapsed ticks in 1s: 24121038

Basic usage with helper:

Number of elapsed ticks in 1s: 24121312

Extended usage: Environment: macos/unix aarch64 Tick frequency, MHZ: 24 Tick frequency is provided by: hardware Tick accuracy, nanoseconds: 41.666666666666664 Tick counter start: 60960038220 Tick counter stop: 60984160104 Elapsed ticks count in ~1 seconds thread::sleep(): 24121884

Elapsed nanoseconds according to elapsed ticks: 1005078500

Comparing the measurement methods using 100 samples: Elapsed time in nanoseconds, using std::time::Instant Mean = 59.58 Min = 41.00 Max = 167.00 Standard deviation = 23.79 (39.93 %) - Elapsed time in nanoseconds, using tick_counter Mean = 42.41 Min = 42.00 Max = 83.00

Standard deviation = 4.08 (9.62 %)

```

2. Ubuntu 22.04 LTS / Intel® Core™ i7

text Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz Linux 6.2.0-31-generic #31~22.04.1-Ubuntu

Output

```text Basic usage:

Number of elapsed ticks in 1s: 3430495113

Basic usage with helper:

Number of elapsed ticks in 1s: 3430495231

Extended usage: Environment: linux/unix x86_64 Tick frequency, MHZ: 3430.494694 Tick frequency is provided by: software, estimated in 1s Tick accuracy, nanoseconds: 0.29150314727173865 Tick counter start: 53632533092006 Tick counter stop: 53635963587302 Elapsed ticks count in ~1 seconds thread::sleep(): 3430495296

Elapsed nanoseconds according to elapsed ticks: 1000000175.4848946

Comparing the measurement methods using 100 samples: Elapsed time in nanoseconds, using std::time::Instant Mean = 46.01 Min = 39.00 Max = 418.00 Standard deviation = 37.46 (81.42 %) - Elapsed time in nanoseconds, using tick_counter Mean = 16.52 Min = 15.00 Max = 17.00

Standard deviation = 0.85 (5.17 %)

```