Implements SystemClock which reads operating system clocks with no overhead.
Supports Darwin (Apple platforms), Linux (Including Android), Windows, FreeBSD, OpenBSD1, WASI and more.
Also compiles (merely) on embedded platforms in a similar fashion to Swift standard library's ContinuousClock.
SystemClock conforms to Clock, so it works just like stdlib's ContinuousClock/SuspendingClock:
import SystemClock
let elapsed: CompactDuration = SystemClock.suspending.measure {
expensiveWork()
}
let now = SystemClock.realtime.nowNote
SystemClock defaults to using CompactDuration although Swift's Duration is also supported.
CompactDuration is a lower-precision Duration that only keeps nanoseconds.
The extra precision is unneeded 99+% of the time in a system-clock context and would be a waste of resources.
You can hand-craft a system clock that uses your desired clocks on each platform:
/// `SystemClock` == `GenericSystemClock<CompactDuration>`
let realtimeClock = SystemClock(
darwin: .realtime,
linux: .realtime,
windows: .systemTimePrecise,
freebsd: .realtimePrecise,
openbsd: .realtime,
wasi: .realtime,
fallback: .realtime
)
/// You can use `Swift.Duration` as well although `CompactDuration` is generally recommended.
let processCPUTimeClock = GenericSystemClock<Swift.Duration>(
darwin: .processCPUTime,
linux: .processCPUTime,
windows: .processTime,
freebsd: .processCPUTime,
openbsd: .processCPUTime,
wasi: .monotonic,
fallback: .monotonic
)Every Apple platform takes darwin. Android takes linux.
Unidentified platforms or platforms with no libc will take fallback which uses std::chrono clocks.
Note
SystemClock will only compile code for the platform you're deploying to.
Essentially, SystemClock is a multi-platform library, but that comes for free with no overhead.
Warning
SystemClock does not support sleeping.
sleep(until:tolerance:) only exists as a requirement of the Clock protocol, and fatal-errors when called.
Task.sleep(for:clock:) and Task.sleep(until:clock:) route through it, so they'll crash too.
Use standard library's ContinuousClock or SuspendingClock instead for sleeping.
For convenience, here is a cheat sheet that should work for most users:
| If you want to | Use |
|---|---|
| ... know what time it is | realtime |
| ... stamp a log line, cheaply | realtimeCoarse |
| If you want to measure how long | Use |
|---|---|
| ... some work took, including system sleeps | continuous / continuousCoarse |
| ... some work took, excluding system sleeps | suspending / suspendingCoarse |
| ... the process spent running on all CPUs, combined | processCPUTime |
| ... the thread spent running on any CPU core | threadCPUTime |
| ... the process spent running in user mode on all CPUs, combined | processUserTime |
| ... the thread spent running in user mode on any CPU core | threadUserTime |
| ... the kernel spent running for this process on all CPUs, combined | processSystemTime |
| ... the kernel spent running for this thread on any CPU core | threadSystemTime |
- "coarse" clocks are cheaper but also less precise. Sometimes you'll have to make that trade-off.
- An example of a system sleep is when you close your laptop's lid.
- An example of the kernel running on behalf of your process is when you read a file, or send data over a socket.
- Generally,
[process/thread]UserTime+[process/thread]SystemTime~=[process/thread]CPUTime.
Note
On WASI, wasi-libc exposes 2 clocks only: monotonic and realtime.
When a clock is unavailable on any platform, SystemClock simply falls back to the best available fit.
- This library supports every clock Unix systems expose via clock_gettime(2).
- For Windows, this library follows Acquiring high-resolution time stamps.
- In few cases, for example for
processUserTimeandthreadUserTime, this library uses alternative functions such as getrusage(2).
Here is a list of all supported clocks on each platform.
macOSwas measured on an M1 Pro (arm64 Apple silicon) under macOS 27, bare metal.Windowson an Intel Core i7-10750H (x86_64) under Windows 11, bare metal.Linuxon Ubuntu 24.04 (kernel 6.8,HZ=1000) in a dedicated-core AMD EPYC Milan x86_64 VM from Hetzner.FreeBSD15.1 andOpenBSD7.9 in arm64 QEMU virtual machines on the same Mac, wherekern.hzis 100.WASIon the same Mac under wasmtime 48 (primary source), Node 26 (uvwasi), Bun 1.3 and WasmKit 0.1.6.
Note
The measured values are meant as general hints.
For better accuracy, measure under your own specific hardware and kernel.
If you find a value generally/widely incorrect, please file an issue or open a pull request for it.
Darwin (Apple platforms)
realtime (CLOCK_REALTIME)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 12ns @ 4GHz |
| Cold read cost | ~ 200ns @ 4GHz |
| Step granularity | 1µs |
monotonic (CLOCK_MONOTONIC)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 17ns @ 4GHz |
| Cold read cost | ~ 165ns @ 4GHz |
| Step granularity | 1µs |
monotonicRaw (CLOCK_MONOTONIC_RAW)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 13ns @ 4GHz |
| Cold read cost | ~ 135ns @ 4GHz |
| Step granularity | 42ns |
monotonicRawApproximate (CLOCK_MONOTONIC_RAW_APPROX)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 0.5-2ms |
| Warm read cost | ~ 5.5ns @ 4GHz |
| Cold read cost | ~ 230ns @ 4GHz |
| Step granularity | 42ns |
uptimeRaw (CLOCK_UPTIME_RAW)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 13ns @ 4GHz |
| Cold read cost | ~ 165ns @ 4GHz |
| Step granularity | 42ns |
uptimeRawApproximate (CLOCK_UPTIME_RAW_APPROX)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 0.5-2ms |
| Warm read cost | ~ 5ns @ 4GHz |
| Cold read cost | ~ 165ns @ 4GHz |
| Step granularity | 42ns |
processCPUTime (CLOCK_PROCESS_CPUTIME_ID)
Measures CPU time used by this process
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads |
| Max staleness | ❌ ~ 10ms, from other threads |
| Warm read cost | ~ 210ns + up to ~ 8ns/thread @ 4GHz |
| Cold read cost | ~ 1.3µs @ 4GHz |
| Step granularity | 1µs |
threadCPUTime (CLOCK_THREAD_CPUTIME_ID)
Measures CPU time used by this thread
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 115ns @ 4GHz |
| Cold read cost | ~ 460ns @ 4GHz |
| Step granularity | 42ns |
processUserTime (RUSAGE_SELF)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time this process spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads |
| Max staleness | ❌ ~ 10ms, from other threads |
| Warm read cost | ~ 210ns + up to ~ 8ns/thread @ 4GHz |
| Cold read cost | ~ 4.3µs @ 4GHz |
| Step granularity | 1µs |
processSystemTime (RUSAGE_SELF)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time the kernel spent on this process's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads |
| Max staleness | ❌ ~ 10ms, from other threads |
| Warm read cost | ~ 210ns + up to ~ 8ns/thread @ 4GHz |
| Cold read cost | ~ 4.5µs @ 4GHz |
| Step granularity | 1µs |
threadUserTime (THREAD_BASIC_INFO)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time this thread spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 460ns @ 4GHz |
| Cold read cost | ~ 5.8µs @ 4GHz |
| Step granularity | 1µs |
threadSystemTime (THREAD_BASIC_INFO)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time the kernel spent on this thread's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 460ns @ 4GHz |
| Cold read cost | ~ 5.2µs @ 4GHz |
| Step granularity | 1µs |
Linux (Including Android)
realtime (CLOCK_REALTIME)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 25ns @ 4GHz |
| Cold read cost | ~ 10.6µs @ 4GHz |
| Step granularity | 20ns |
realtimeAlarm (CLOCK_REALTIME_ALARM)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 135ns @ 4GHz |
| Cold read cost | ~ 4.6µs @ 4GHz |
| Step granularity | 140ns |
realtimeCoarse (CLOCK_REALTIME_COARSE)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 1ms @ HZ 1000 |
| Warm read cost | ~ 4.5ns @ 4GHz |
| Cold read cost | ~ 9µs @ 4GHz |
| Step granularity | 1ms @ HZ 1000 |
tai (CLOCK_TAI)
Measures Wall time, on the TAI timescale
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 25ns @ 4GHz |
| Cold read cost | ~ 10.8µs @ 4GHz |
| Step granularity | 20ns |
monotonic (CLOCK_MONOTONIC)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 25ns @ 4GHz |
| Cold read cost | ~ 10.8µs @ 4GHz |
| Step granularity | 20ns |
monotonicCoarse (CLOCK_MONOTONIC_COARSE)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 1ms @ HZ 1000 |
| Warm read cost | ~ 4.5ns @ 4GHz |
| Cold read cost | ~ 9µs @ 4GHz |
| Step granularity | 1ms @ HZ 1000 |
monotonicRaw (CLOCK_MONOTONIC_RAW)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 25ns @ 4GHz |
| Cold read cost | ~ 10.6µs @ 4GHz |
| Step granularity | 20ns |
boottime (CLOCK_BOOTTIME)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 25ns @ 4GHz |
| Cold read cost | ~ 11.2µs @ 4GHz |
| Step granularity | 20ns |
boottimeAlarm (CLOCK_BOOTTIME_ALARM)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 140ns @ 4GHz |
| Cold read cost | ~ 4.9µs @ 4GHz |
| Step granularity | 140ns |
processCPUTime (CLOCK_PROCESS_CPUTIME_ID)
Measures CPU time used by this process
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads |
| Max staleness | ❌ ~ 1ms @ HZ 1000, from other threads |
| Warm read cost | ~ 165ns + ~ 6ns/thread @ 4GHz |
| Cold read cost | ~ 7µs @ 4GHz |
| Step granularity | 170ns |
threadCPUTime (CLOCK_THREAD_CPUTIME_ID)
Measures CPU time used by this thread
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 160ns @ 4GHz |
| Cold read cost | ~ 6.5µs @ 4GHz |
| Step granularity | 160ns |
processUserTime (RUSAGE_SELF)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time this process spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads |
| Max staleness | ❌ ~ 1ms @ HZ 1000, from other threads |
| Warm read cost | ~ 220ns + ~ 12ns/thread @ 4GHz |
| Cold read cost | ~ 4µs @ 4GHz |
| Step granularity | 1µs |
processSystemTime (RUSAGE_SELF)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time the kernel spent on this process's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads |
| Max staleness | ❌ ~ 1ms @ HZ 1000, from other threads |
| Warm read cost | ~ 220ns + ~ 12ns/thread @ 4GHz |
| Cold read cost | ~ 3.5µs @ 4GHz |
| Step granularity | 1µs |
threadUserTime (RUSAGE_THREAD)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time this thread spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 1ms @ HZ 1000 |
| Warm read cost | ~ 150ns @ 4GHz |
| Cold read cost | ~ 3.1µs @ 4GHz |
| Step granularity | ~ 1ms @ HZ 1000 |
threadSystemTime (RUSAGE_THREAD)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time the kernel spent on this thread's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 1ms @ HZ 1000 |
| Warm read cost | ~ 150ns @ 4GHz |
| Cold read cost | ~ 2.7µs @ 4GHz |
| Step granularity | ~ 1ms @ HZ 1000 |
Windows
performanceCounter (QueryPerformanceCounter)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 10ns @ 4GHz |
| Cold read cost | ~ 230ns @ 4GHz |
| Step granularity | 100ns |
systemTime (GetSystemTimeAsFileTime)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 16ms @ 64Hz tick |
| Warm read cost | ~ 4ns @ 4GHz |
| Cold read cost | ~ 1.5µs @ 4GHz |
| Step granularity | ~ 0.5ms |
systemTimePrecise (GetSystemTimePreciseAsFileTime)
GetSystemTimePreciseAsFileTime
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 16ns @ 4GHz |
| Cold read cost | ~ 2µs @ 4GHz |
| Step granularity | 100ns |
interruptTime (QueryInterruptTime)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 16ms @ 64Hz tick |
| Warm read cost | ~ 2ns @ 4GHz |
| Cold read cost | ~ 1.9µs @ 4GHz |
| Step granularity | ~ 0.5ms |
interruptTimePrecise (QueryInterruptTimePrecise)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 14ns @ 4GHz |
| Cold read cost | ~ 330ns @ 4GHz |
| Step granularity | 100ns |
unbiasedInterruptTime (QueryUnbiasedInterruptTime)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 16ms @ 64Hz tick |
| Warm read cost | ~ 3ns @ 4GHz |
| Cold read cost | ~ 1.9µs @ 4GHz |
| Step granularity | ~ 0.5ms |
unbiasedInterruptTimePrecise (QueryUnbiasedInterruptTimePrecise)
QueryUnbiasedInterruptTimePrecise
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 14ns @ 4GHz |
| Cold read cost | ~ 2.3µs @ 4GHz |
| Step granularity | 100ns |
tickCount (GetTickCount64)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 18ms @ 64Hz tick |
| Warm read cost | ~ 1.5ns @ 4GHz |
| Cold read cost | ~ 1.8µs @ 4GHz |
| Step granularity | 15ms |
processTime (GetProcessTimes)
Measures CPU time used by this process
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for all threads |
| Max staleness | ❌ ~ 15.6ms @ 64Hz tick, from all threads |
| Warm read cost | ~ 120ns + up to ~ 8ns/thread @ 4GHz |
| Cold read cost | ~ 2.6µs @ 4GHz |
| Step granularity | 15.625ms @ 64Hz tick |
threadTime (GetThreadTimes)
Measures CPU time used by this thread
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 15.6ms @ 64Hz tick |
| Warm read cost | ~ 86ns @ 4GHz |
| Cold read cost | ~ 585ns @ 4GHz |
| Step granularity | 15.625ms @ 64Hz tick |
processUserTime (GetProcessTimes)
One half of the pair GetProcessTimes reports; processTime and threadTime read them summed.
Measures CPU time this process spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for all threads |
| Max staleness | ❌ ~ 15.6ms @ 64Hz tick, from all threads |
| Warm read cost | ~ 113ns + up to ~ 8ns/thread @ 4GHz |
| Cold read cost | ~ 2.7µs @ 4GHz |
| Step granularity | 15.625ms @ 64Hz tick |
processKernelTime (GetProcessTimes)
One half of the pair GetProcessTimes reports; processTime and threadTime read them summed.
Measures CPU time the kernel spent on this process's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for all threads |
| Max staleness | ❌ ~ 15.6ms @ 64Hz tick, from all threads |
| Warm read cost | ~ 115ns + up to ~ 8ns/thread @ 4GHz |
| Cold read cost | ~ 2.8µs @ 4GHz |
| Step granularity | 15.625ms @ 64Hz tick |
threadUserTime (GetThreadTimes)
One half of the pair GetThreadTimes reports; processTime and threadTime read them summed.
Measures CPU time this thread spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 15.6ms @ 64Hz tick |
| Warm read cost | ~ 87ns @ 4GHz |
| Cold read cost | ~ 610ns @ 4GHz |
| Step granularity | 15.625ms @ 64Hz tick |
threadKernelTime (GetThreadTimes)
One half of the pair GetThreadTimes reports; processTime and threadTime read them summed.
Measures CPU time the kernel spent on this thread's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 15.6ms @ 64Hz tick |
| Warm read cost | ~ 87ns @ 4GHz |
| Cold read cost | ~ 630ns @ 4GHz |
| Step granularity | 15.625ms @ 64Hz tick |
FreeBSD
realtime (CLOCK_REALTIME)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 300ns @ 4GHz |
| Step granularity | 42ns |
realtimePrecise (CLOCK_REALTIME_PRECISE)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 365ns @ 4GHz |
| Step granularity | 42ns |
realtimeFast (CLOCK_REALTIME_FAST)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 265ns @ 4GHz |
| Step granularity | 42ns |
monotonic (CLOCK_MONOTONIC)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 265ns @ 4GHz |
| Step granularity | 42ns |
monotonicPrecise (CLOCK_MONOTONIC_PRECISE)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 265ns @ 4GHz |
| Step granularity | 42ns |
monotonicFast (CLOCK_MONOTONIC_FAST)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 1ms @ kern.hz 1000 |
| Warm read cost | ~ 3.5ns @ 4GHz |
| Cold read cost | ~ 235ns @ 4GHz |
| Step granularity | 1ms @ kern.hz 1000 |
uptime (CLOCK_UPTIME)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 265ns @ 4GHz |
| Step granularity | 42ns |
uptimePrecise (CLOCK_UPTIME_PRECISE)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 265ns @ 4GHz |
| Step granularity | 42ns |
uptimeFast (CLOCK_UPTIME_FAST)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 1ms @ kern.hz 1000 |
| Warm read cost | ~ 3.5ns @ 4GHz |
| Cold read cost | ~ 265ns @ 4GHz |
| Step granularity | 1ms @ kern.hz 1000 |
boottime (CLOCK_BOOTTIME)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 395ns @ 4GHz |
| Step granularity | 42ns |
tai (CLOCK_TAI)
Measures Wall time, on the TAI timescale
Rejected with EINVAL until the machine's TAI offset has been set. Traps on runtime.
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 120ns @ 4GHz |
| Cold read cost | ~ 695ns @ 4GHz |
| Step granularity | 125ns |
virtual (CLOCK_VIRTUAL)
Measures CPU time used by this process, user mode only
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads and the user/system ratio |
| Max staleness | ❌ ~ 8ms @ stathz 127 |
| Warm read cost | ~ 145ns + up to ~ 10ns/thread @ 4GHz |
| Cold read cost | ~ 495ns @ 4GHz |
| Step granularity | 1µs |
prof (CLOCK_PROF)
Measures CPU time used by this process
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads and the user/system ratio |
| Max staleness | ❌ ~ 8ms @ stathz 127 |
| Warm read cost | ~ 145ns + up to ~ 10ns/thread @ 4GHz |
| Cold read cost | ~ 560ns @ 4GHz |
| Step granularity | 1µs |
second (CLOCK_SECOND)
Measures Wall time, whole seconds only
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ❌ ~ 1s |
| Warm read cost | ~ 18ns @ 4GHz |
| Cold read cost | ~ 265ns @ 4GHz |
| Step granularity | 1s |
processCPUTime (CLOCK_PROCESS_CPUTIME_ID)
Measures CPU time used by this process
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads |
| Max staleness | ❌ ~ 8ms @ stathz 127, from other threads |
| Warm read cost | ~ 145ns + ~ 11ns/thread @ 4GHz |
| Cold read cost | ~ 595ns @ 4GHz |
| Step granularity | 170ns |
threadCPUTime (CLOCK_THREAD_CPUTIME_ID)
Measures CPU time used by this thread
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 120ns @ 4GHz |
| Cold read cost | ~ 495ns @ 4GHz |
| Step granularity | 125ns |
processUserTime (RUSAGE_SELF)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time this process spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads and the user/system ratio |
| Max staleness | ❌ ~ 8ms @ stathz 127 |
| Warm read cost | ~ 150ns + ~ 16ns/thread @ 4GHz |
| Cold read cost | ~ 490ns @ 4GHz |
| Step granularity | 1µs |
processSystemTime (RUSAGE_SELF)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time the kernel spent on this process's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads and the user/system ratio |
| Max staleness | ❌ ~ 8ms @ stathz 127 |
| Warm read cost | ~ 150ns + ~ 16ns/thread @ 4GHz |
| Cold read cost | ~ 490ns @ 4GHz |
| Step granularity | 1µs |
threadUserTime (RUSAGE_THREAD)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time this thread spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for the user/system ratio |
| Max staleness | ❌ ~ 8ms @ stathz 127 |
| Warm read cost | ~ 145ns @ 4GHz |
| Cold read cost | ~ 425ns @ 4GHz |
| Step granularity | 1µs |
threadSystemTime (RUSAGE_THREAD)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time the kernel spent on this thread's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for the user/system ratio |
| Max staleness | ❌ ~ 8ms @ stathz 127 |
| Warm read cost | ~ 145ns @ 4GHz |
| Cold read cost | ~ 425ns @ 4GHz |
| Step granularity | 1µs |
OpenBSD
realtime (CLOCK_REALTIME)
Measures Wall time, counted from 1970-01-01 UTC
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 21ns @ 4GHz |
| Cold read cost | ~ 19.7µs @ 4GHz |
| Step granularity | 42ns |
monotonic (CLOCK_MONOTONIC)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 20ns @ 4GHz |
| Cold read cost | ~ 21.9µs @ 4GHz |
| Step granularity | 42ns |
boottime (CLOCK_BOOTTIME)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 20ns @ 4GHz |
| Cold read cost | ~ 18.2µs @ 4GHz |
| Step granularity | 42ns |
uptime (CLOCK_UPTIME)
Measures Elapsed time, since the machine booted
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 20ns @ 4GHz |
| Cold read cost | ~ 15.9µs @ 4GHz |
| Step granularity | 42ns |
processCPUTime (CLOCK_PROCESS_CPUTIME_ID)
Measures CPU time used by this process
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for other threads |
| Max staleness | ❌ ~ 200ms, from other threads |
| Warm read cost | ~ 235ns + ~ 5ns/thread @ 4GHz |
| Cold read cost | ~ 15.4µs @ 4GHz |
| Step granularity | 291ns |
threadCPUTime (CLOCK_THREAD_CPUTIME_ID)
Measures CPU time used by this thread
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ✅ No |
| Max staleness | ✅ None |
| Warm read cost | ~ 195ns @ 4GHz |
| Cold read cost | ~ 15.5µs @ 4GHz |
| Step granularity | 125ns |
processUserTime (RUSAGE_SELF)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time this process spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for all threads |
| Max staleness | ❌ ~ 10ms @ stathz 100, from all threads |
| Warm read cost | ~ 190ns + ~ 11ns/thread @ 4GHz |
| Cold read cost | ~ 5µs @ 4GHz |
| Step granularity | 10ms @ stathz 100 |
processSystemTime (RUSAGE_SELF)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time the kernel spent on this process's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while process is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes, for all threads |
| Max staleness | ❌ ~ 10ms @ stathz 100, from all threads |
| Warm read cost | ~ 190ns + ~ 11ns/thread @ 4GHz |
| Cold read cost | ~ 5µs @ 4GHz |
| Step granularity | 10ms @ stathz 100 |
threadUserTime (RUSAGE_THREAD)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time this thread spent running its own code
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 10ms @ stathz 100 |
| Warm read cost | ~ 215ns @ 4GHz |
| Cold read cost | ~ 4.5µs @ 4GHz |
| Step granularity | 10ms @ stathz 100 |
threadSystemTime (RUSAGE_THREAD)
This is this library's own clock identifier and not one of the clock ids the platform declares.
Measures CPU time the kernel spent on this thread's behalf
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | ✅ No |
| Advances while thread is de-scheduled | ✅ No |
| Might appear to go backwards | ✅ No |
| Reads a cached value | ❌ Yes |
| Max staleness | ❌ ~ 10ms @ stathz 100 |
| Warm read cost | ~ 215ns @ 4GHz |
| Cold read cost | ~ 4.5µs @ 4GHz |
| Step granularity | 10ms @ stathz 100 |
WASI
realtime (CLOCK_REALTIME)
Measures Wall time, counted from 1970-01-01 UTC
Whether it actually counts from 1970 (not e.g. boot time) is runtime-dependent.
| Property | Value |
|---|---|
| Reacts to OS time changes | Runtime-dependent |
| Reacts to NTP changes | Runtime-dependent |
| Counts system suspension times | Runtime-dependent |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | Runtime-dependent |
| Reads a cached value | Runtime-dependent |
| Max staleness | ✅ None |
| Warm read cost | ~ 29-282ns; ~ 57ns on wasmtime @ 4GHz |
| Cold read cost | N/A |
| Step granularity | 1µs on wasmtime |
monotonic (CLOCK_MONOTONIC)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | Runtime-dependent |
| Counts system suspension times | Runtime-dependent |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | Runtime-dependent |
| Max staleness | ✅ None |
| Warm read cost | ~ 25-284ns; ~ 56ns on wasmtime @ 4GHz |
| Cold read cost | N/A |
| Step granularity | 42ns on wasmtime |
Fallback
monotonic (std::chrono::steady_clock)
Measures Elapsed time, from an arbitrary point
| Property | Value |
|---|---|
| Reacts to OS time changes | ✅ No |
| Reacts to NTP changes | ✅ No |
| Counts system suspension times | Implementation-dependant |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ✅ No |
| Reads a cached value | Implementation-dependant |
| Max staleness | Implementation-dependant |
| Warm read cost | Implementation-dependant |
| Cold read cost | Implementation-dependant |
| Step granularity | Implementation-dependant |
realtime (std::chrono::system_clock)
Measures Wall time, counted from 1970-01-01 UTC (guaranteed since C++20)
| Property | Value |
|---|---|
| Reacts to OS time changes | ❌ Yes |
| Reacts to NTP changes | ❌ Yes |
| Counts system suspension times | ❌ Yes |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | ❌ Yes |
| Reads a cached value | Implementation-dependant |
| Max staleness | Implementation-dependant |
| Warm read cost | Implementation-dependant |
| Cold read cost | Implementation-dependant |
| Step granularity | Implementation-dependant |
highResolution (std::chrono::high_resolution_clock)
Measurements dependant on the underlying implementation: monotonic on libc++ and Microsoft's STL, realtime on libstdc++
| Property | Value |
|---|---|
| Reacts to OS time changes | Implementation-dependant |
| Reacts to NTP changes | Implementation-dependant |
| Counts system suspension times | Implementation-dependant |
| Advances while thread is de-scheduled | ❌ Yes |
| Might appear to go backwards | Implementation-dependant |
| Reads a cached value | Implementation-dependant |
| Max staleness | Implementation-dependant |
| Warm read cost | Implementation-dependant |
| Cold read cost | Implementation-dependant |
| Step granularity | Implementation-dependant |
- Below are benchmarks of this library against the 2 clocks that Swift standard library provides, on macOS and Linux.
- That is,
SystemClock's.continuous/.suspendingvs. stdlib'sContinuousClock/SuspendingClock. - The instruction tables contain most other clocks supported by
SystemClockas well for comparison.
- That is,
- In all cases, swift-system-clock wins against the Swift standard library APIs.
N/Ameans unsupported clock.
These were performed on my M1 Pro MacBook, on macOS 27.
| Benchmark | SystemClock (ns/op) |
Standard Library (ns/op) | Speedup |
|---|---|---|---|
continuous.now |
10.6 ns | 24.7 ns | 2.34x |
suspending.now |
10.8 ns | 23.1 ns | 2.14x |
| Benchmark | SystemClock instructions |
Standard Library instructions |
|---|---|---|
realtime.now |
146 | N/A |
realtimeCoarse.now |
146 | N/A |
continuous.now |
94 | 205 |
continuousCoarse.now |
104 | N/A |
suspending.now |
101 | 210 |
suspendingCoarse.now |
91 | N/A |
These were performed on a dedicated-cpu-core AMD EPYC-Milan VM from Hetzner, on Ubuntu 24.04.
| Benchmark | SystemClock (ns/op) |
Standard Library (ns/op) | Speedup |
|---|---|---|---|
continuous.now |
27.5 ns | 29.8 ns | 1.08x |
suspending.now |
27.5 ns | 29.5 ns | 1.07x |
| Benchmark | SystemClock instructions |
Standard Library instructions |
|---|---|---|
realtime.now |
132 | N/A |
realtimeCoarse.now |
86 | N/A |
continuous.now |
132 | 200 |
continuousCoarse.now |
132 | N/A |
suspending.now |
132 | 198 |
suspendingCoarse.now |
86 | N/A |
- To see up to date information about performance of this package, please go to this benchmarks list, and choose the most recent benchmark. You'll see a summary of the benchmark there.
- The results above are all reproducible by simply running
scripts/benchmark.shon a machine of your own.
Footnotes
-
Swift support for
OpenBSDis a work-in-progress. This library doesn't have CI forOpenBSDyet so things can be flaky. ↩