Reading the cycle counter¶
Level: 301 · deep dive
Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.
One line: The CPU's time-stamp counter can be read in one instruction, faster than any clock the library offers — and reading it honestly means fighting out-of-order execution, knowing the counter's frequency, and accepting that the other CI runner has a different instruction for it.
The questions this page has to answer¶
- What is the time-stamp counter, read by
rdtscandrdtscp, and what does invariant mean? The talk: stable since Pentium 4, invariant since Nehalem. ARM's counterpart isCNTVCT_EL0. - Why does
asm("rdtsc" …)needvolatileto survive the optimizer, and why is__builtin_ia32_rdtsc()the better spelling? - Out-of-order execution means the counter may be read before earlier work finishes or after later work starts. What does
rdtscpwait for, what does it not, and where do thelfenceinstructions go? - The talk times three chained
idivs:rdtscabout 111 ns,rdtscpabout 187 ns, fenced about 159 ns. Which one is right, and why does the unfenced read come out low? - Wrapping the counter as a
std::chronoclock (What a clock is): what goes inperiodwhen a tick is one cycle of a frequency you have to measure? - One CI runner is x86-64 and the other arm64. What can an answer key hold here — or does the whole page live in dated fences?
In the talk¶
When will then be now()? — from Hardware counters to Which clock to use? (slide source ↗).
See also¶
- What a clock is
- The cost of asking the time
- The optimizer deletes your benchmark — the
asm volatilemachinery this page reuses