How Computers Keep Accurate Time: Early Counters to Modern TSC

 19 min video

 6 min read

YouTube video ID: xs5iOwkX9fU

Source: YouTube video by ComputerphileWatch original video

PDF

This article delves into how computers keep track of time, from early systems to modern high-performance computing, and the complexities involved in accurate time measurement.

Early Computers and Basic Timekeeping

Early computers, such as the ZX Spectrum and BBC Micro, didn't possess a real-world clock. Instead, they measured elapsed time. This was typically achieved by incrementing a counter every time a specific hardware interrupt occurred. For instance, an interrupt signaling the video chip was about to redraw the screen (often 50 times per second) would trigger the counter. To display the time, a program would simply read this counter and divide it by 50 to determine how many seconds had passed since the computer was powered on. Later, some systems incorporated battery-backed clocks that stored the actual time, which the computer would read at startup and then continue to update using the interrupt-driven counter.

Modern Computers and High-Resolution Timers

Modern computers require much finer granularity for timekeeping than 50 times per second. Since the early 2000s, most CPUs include a built-in counter that ticks at a significantly higher frequency. For example, a typical CPU might have a counter that increments at 3 GHz. This high-frequency counter allows for very precise measurements, potentially down to individual instruction cycles.

From Counter Ticks to Wall Clock Time

When a computer boots up, this counter starts at zero. To translate this raw count into a meaningful wall clock time (e.g., 3:30 PM), the operating system performs a calibration step. It might query a battery-backed clock in the BIOS or synchronize with a network time server (like NTP) to get an initial "time at boot." This provides a base offset.

The challenge then becomes converting the CPU's internal tick count into standard time units like nanoseconds. The CPU itself can report its clock frequency (e.g., 3 GHz). However, this factory-set frequency might not be perfectly accurate due to manufacturing variations or environmental factors like temperature.

The RDTSC Instruction

On x86 architectures, the rdtsc (read timestamp counter) instruction is used to retrieve the current value of this high-frequency counter. This instruction is designed to be fast, as time queries are frequent.

To calculate the current time in nanoseconds since a specific epoch (e.g., January 1, 1970, in Unix systems), the following formula is conceptually applied:

Nanoseconds_at_Current_Time = Nanoseconds_at_Boot + (Current_TSC_Value * Factor / Shift)

Where: - Nanoseconds_at_Boot is the time in nanoseconds at which the system booted, obtained from an external source. - Current_TSC_Value is the value returned by rdtsc. - Factor and Shift are pre-calculated integer values used to convert the TSC ticks into nanoseconds without using slow floating-point arithmetic. This involves multiplying by an integer and then right-shifting (dividing by a power of two), which is computationally efficient. For example, to approximate dividing by 3, one might multiply by 85 and then shift right by 8 (effectively dividing by 256).

Addressing Clock Skew and Drift

The initial frequency reported by the CPU is an approximation. Real-world clocks, like those in Casio watches, can drift by a few seconds a day. Similarly, CPU clocks are not perfectly stable. Factors like temperature can cause slight variations in their speed.

To maintain accuracy, operating systems like Linux continuously monitor the system's time against external sources (e.g., NTP servers). If a discrepancy is detected, the Factor used in the time calculation is subtly adjusted. This "wafting" ensures that time adjustments are gradual, preventing sudden jumps or discontinuities that could confuse applications.

Furthermore, the initial Nanoseconds_at_Boot value is also subject to an offset. The time it takes for the kernel to boot and establish an accurate time source means that the first "accurate" time reading isn't truly at the exact moment of boot. This leads to a more generalized formula:

Current_Nanoseconds = Time_Offset + ((Current_TSC - TSC_at_Offset) * Factor / Shift)

Here: - Time_Offset is the last known accurate wall clock time. - TSC_at_Offset is the timestamp counter value when Time_Offset was recorded.

This allows the system to periodically update Time_Offset and TSC_at_Offset whenever a more accurate time source becomes available, ensuring the system's clock remains synchronized.

CPU Frequency Scaling and Timekeeping

An important consideration is that modern CPUs can dynamically change their clock speed for power saving or performance boosting. Early versions of rdtsc would reflect these changes, making it difficult to get a stable time measurement. However, modern CPUs have a dedicated, stable base clock that all cores use, which does not change even if individual cores speed up or slow down. This ensures that rdtsc provides a consistent, monotonically increasing count.

Optimizing Time Queries

Making a system call to the operating system to get the time is a relatively expensive operation. To make time queries faster, Linux employs a clever technique: it maps certain time-related values (the Time_Offset, TSC_at_Offset, Factor, and Shift) into a read-only memory area accessible by user-space programs. This allows applications to perform the time calculation directly without needing to enter kernel mode, significantly reducing the overhead. This process can take as little as 35 nanoseconds.

Time Measurement for Performance Analysis

When benchmarking or profiling code, the absolute wall clock time is often less important than the duration between two events. In such cases, the Time_Offset and TSC_at_Offset effectively cancel out. The process involves:

  1. Reading the TSC value (TSC_Start).
  2. Executing the code to be measured.
  3. Reading the TSC value again (TSC_End).
  4. Calculating the difference: Elapsed_Ticks = TSC_End - TSC_Start.
  5. Converting Elapsed_Ticks to nanoseconds using the Factor and Shift.

For simple comparisons (e.g., "is this faster than that?"), even the conversion to nanoseconds might be skipped, as comparing raw tick counts is sufficient.

The Challenge of Instruction Reordering

A critical issue in accurate time measurement, especially at the microsecond or nanosecond level, is CPU instruction reordering. Modern CPUs execute instructions out of order to maximize efficiency. If rdtsc is called, the CPU might execute it earlier than intended if it doesn't depend on previous instructions. This can lead to inaccurate measurements, as the TSC_Start might be recorded before the actual start of the benchmarked code.

To address this, specialized instructions are used: - RDTSCP: This instruction (introduced by AMD and later adopted by Intel) ensures that all preceding instructions have completed before rdtscp executes. It also returns additional information. - Serializing Instructions: For even stricter control, instructions like CPUID can be used. CPUID forces the CPU to complete all prior instructions and prevents subsequent instructions from starting until CPUID itself has finished. This creates a strong "fence" around the measured code, preventing instruction leakage into or out of the benchmarked region. Other memory fence instructions can also be used for similar purposes.

Measuring time accurately on computers, particularly at high resolutions, is a complex task involving careful consideration of hardware capabilities, operating system mechanisms, and CPU microarchitectural behaviors.

  Takeaways

  • Early computers lacked real-time clocks and used hardware interrupts, such as a 50 Hz video refresh, to increment a counter and derive elapsed seconds.
  • Modern CPUs include high‑frequency timestamp counters accessed via the `rdtsc` instruction, enabling nanosecond‑level measurements.
  • Operating systems calibrate the raw counter with a boot‑time offset from a battery‑backed RTC or NTP and convert ticks to nanoseconds using pre‑computed integer Factor and Shift values.
  • To maintain accuracy despite clock drift and frequency scaling, OSes periodically adjust the conversion factor and update offset values, while modern CPUs provide a stable base clock for reliable `rdtsc` counts.
  • High‑performance time queries avoid system calls by mapping conversion parameters into user‑space memory, and precise benchmarking uses serialization instructions like `rdtscp` or `cpuid` to prevent instruction reordering.

Frequently Asked Questions

What is the purpose of the Factor and Shift values in converting TSC ticks to nanoseconds?

The Factor and Shift are pre‑computed integer constants that replace floating‑point division when translating raw TSC ticks into nanoseconds. Multiplying the tick count by the Factor and then right‑shifting by Shift approximates the division by the CPU frequency, allowing fast, kernel‑level time calculations without costly floating‑point operations.

How does the RDTSCP instruction improve timing accuracy compared to RDTSC?

RDTSCP serializes execution by waiting for all prior instructions to complete before reading the timestamp counter, and it also returns the current processor ID. This prevents the out‑of‑order execution that can cause RDTSC to be taken early, yielding more reliable measurements for fine‑grained benchmarking.

Who is Computerphile on YouTube?

Computerphile is a YouTube channel that publishes videos on a range of topics. Browse more summaries from this channel below.

Does this page include the full transcript of the video?

Yes, the full transcript for this video is available on this page. Click 'Show transcript' in the sidebar to read it.

Helpful resources related to this video

If you want to practice or explore the concepts discussed in the video, these commonly used tools may help.

Links may be affiliate links. We only include resources that are genuinely relevant to the topic.

Full transcript is not shown on this page

This page focuses on the summary and original notes. For full verification, refer to the original YouTube video.

PDF