The Dual Clocks of Computing: Time-of-Day and Monotonic
Our computers have two clocks:
- The time of day clock (also: wall-clock time).
- The monotonic clock.
The following lines are dedicated to them.
*Imagine The Persistence of Memory by Salvador Dali inserted here.*
Time-of-day clocks
The time-of-day clock returns the current time in accordance to a calendar.
This is what you get when calling System.currentTimeMillis() in Java. It returns the passed time since January 1, 1970, midnight (UTC) using the Gregorian calendar and doesn’t count leap seconds.
When you call date on a UNIX machine you get the current date.
One issue with time-of-day clocks is that they are not really reliable. Users or system administrators can change the time.
Furthermore the components behavior which is responsible for computing the time is also affected by its environment.
The component is called quartz clock (or: Real-Time clock) and is responsible for counting the time. But this component is not accurate, as it drifts due to environmental factors like temperature and slight imperfections in the crystal. This can introduce errors.
To minimize excessive drift from real-world time, our computers synchronize with Network Time Protocol (NTP).
You can track this drift and synchronization with different tools or commands like the chronyc tracking command.
While synchronization is beneficial for accuracy, it can cause the system time to jump forward or backward. Furthermore, the omission of leap seconds can complicate reliance on this time.
Monotonic clocks
Monotonic clocks move forward and show how much time has passed since an event. This can be for example the time since the startup of the system.
You get that time when you call System.nanoTime() in Java.
The CLI command gives you the time passed since you started the machine:
cat /proc/uptime | awk '{print $1}'
The absolute value of the monotonic clock is not so interesting. But, a monotonic clock can be helpful when measuring the elapsed time between two checks. Just call the monotonic clock at point A and call it then at point B. The difference between both of them is the time passed between the events.
Maybe you already worked with this snippet:
long start = System.nanoTime();
// more code here...
long end = System.nanoTime();
long elapsed = finish - end;
NTP doesn’t make the monotonic clock jump forward or backward. So, the monotonic clock is not affected by system clock changes. But NTP can speed it up or slow it down. This is also known as slewing the clock.
Summarized this means that the monotonic clock can move slower or faster. That’s important to know when comparing two events.
Conclusion
This post had a look on the two types of clocks by computers. The time-of-day clock gives you the actual time and the monotonic clock the time which has passed since an event.
The two clocks serve different purposes and knowing the difference can be helpful. But generally they’re not reliable. This is important to know when working with distributed systems as it can affect the order of events. Solving this problem will be part of another post.
See also
-
Leap Second crashes half the internet - somebits.com An interesting piece which shows how important it is to be aware of leap seconds.
-
High Precision Event Timer - wikipedia.org The alternative solution to the Real-time clock.
-
NTP specification - datatracker.ietf.org The specification of the NTP protocol.
-
NTP Implementation in Elixir - 0x7f.dev Here you can see the most interesting details of the NTP protocol reverse engineered. And no, you don’t need to Elixir to read this post.
-
The day my ping took countermeasures - blog.cloudflare.com More interesting information about the effect of clock drifts and how to handle them.