Summary
std::chrono::system_clock can move backwards on Linux because it reflects the system’s real-time clock, which can be adjusted by NTP or other time-correction mechanisms. When the OS steps the clock backward, your process observes that jump. It is not monotonic and never guaranteed to be.
For monotonic timestamps, use std::chrono::steady_clock.
Root Cause
The backward time movement occurs because:
system_clockmaps directly to the kernel’s real-time clock, which is allowed to jump forward or backward.- NTP can “step” the clock when the drift is too large to correct gradually. This step may move time backward.
- Kernel time adjustments under load (e.g., frequency corrections, clock skew compensation) can cause small backward shifts.
- Real-time clock (RTC) corrections may propagate into the system clock.
Why This Happens in Real Systems
Real-world Linux systems frequently adjust their clocks:
- NTP synchronization: When drift exceeds a threshold, NTP performs a backward step instead of a slow correction.
- Virtualized or heavily loaded environments: CPU scheduling delays and TSC instability can cause non-monotonic readings.
- Hardware clock inconsistencies: RTC updates or corrections can cause sudden jumps.
- Clock discipline algorithms: The kernel may apply corrections that temporarily reduce the reported time.
Real-World Impact
Backward time jumps can break:
- Log ordering, making debugging extremely difficult.
- Timeout logic, causing timers to fire late or never.
- ID generation, especially if timestamps are part of uniqueness guarantees.
- Event sequencing, where ordering depends on timestamp monotonicity.
Example or Code (if necessary and relevant)
Below is an example of switching to a monotonic clock:
#include
#include
int main() {
using clock = std::chrono::steady_clock;
auto t1 = clock::now();
// some work
auto t2 = clock::now();
if (t2 < t1) {
std::cout << "steady_clock moved backwards\n";
}
}
How Senior Engineers Fix It
Experienced engineers avoid system_clock for sequencing or measuring durations:
- Use
steady_clockfor monotonic timestamps. - Use
high_resolution_clockonly if it aliases to a monotonic clock (implementation-dependent). - Use
system_clockonly for human-readable wall time, not for ordering or measuring intervals. - Design systems to tolerate clock adjustments, especially in distributed environments.
Why Juniors Miss It
Common misconceptions include:
- Assuming “time always moves forward” inside a process.
- Believing that NTP only slews time, not realizing it can step backward.
- Confusing wall-clock time with monotonic time.
- Not knowing that
system_clockis not monotonic by design and is tied to OS-level adjustments.
Senior engineers learn early that monotonicity is a property you must explicitly choose, not something the system guarantees by default.