<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/a-clock-made-of-branches-bxrqnrnxg" -->

---
title: A clock made of branches | daily.dev
description: Rewind, a deterministic VM, needs a clock that behaves the same on every replay, so it can't use host wall-clock time. Its 'exit time' mode advances 5...
canonical: https://daily.dev/posts/a-clock-made-of-branches-bxrqnrnxg
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: A clock made of branches | daily.dev
og:description: Rewind, a deterministic VM, needs a clock that behaves the same on every replay, so it can't use host wall-clock time. Its 'exit time' mode advances 5...
og:url: https://daily.dev/posts/a-clock-made-of-branches-bxrqnrnxg
og:image: https://api.daily.dev/og/posts/bXrqnrnXg.png
og:image:alt: A clock made of branches
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# A clock made of branches

**[Farid Zakaria’s Blog](https://daily.dev/sources/fzakaria)** · 6 min read · 0 upvotes · 0 comments

## Summary

Rewind, a deterministic VM, needs a clock that behaves the same on every replay, so it can't use host wall-clock time. Its 'exit time' mode advances 5 microseconds per guest exit (like a syscall) and treats everything between exits as instant. Its 'counter time' mode instead advances one nanosecond per retired conditional branch, an approach also used by the rr debugger. Testing a billion-iteration countdown loop with perf stat shows the conditional branch counter stays exact across runs, while the raw instruction counter drifts due to interrupts and page faults. AMD Zen chips also overcount branches via a speculation quirk called SpecLockMap, fixed with a PMU MSR bit. In a table of times, exit time showed 2.1s of VM time for 15.7s of host time, while counter time showed 11.7s VM time for 14.2s host time, making it more realistic for timeout and race-condition bugs.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://fzakaria.com/2026/11/01/a-clock-made-of-branches>

## Questions this post answers

### why does the instruction count from perf stat vary between identical runs of the same program

Instruction counts drift because the CPU's instruction counter also captures interrupts from outside the program, such as timer ticks, network packet arrivals, inter-processor interrupts, and page faults. Running the same billion-iteration decrement loop twice showed instruction counts of 2,000,001,025 and 2,000,001,054, a difference tied almost exactly to the number of hardware interrupts the pinned CPU took during each run.

_daily.dev surfaces performance-counter deep dives for engineers debugging nondeterministic profiling results._

### how can I get a deterministic measurement of CPU time for record-replay debugging

Counting retired conditional branches gives a deterministic proxy for time, since this count stays identical across runs of the same program even when the instruction count drifts due to interrupts. The rr debugger popularized this technique, calling it 'deterministic time,' advancing a virtual clock by one nanosecond per conditional branch retired by the guest.

_Developers building replay or record-and-replay tooling track techniques like this one on daily.dev._

### why does AMD Zen overcount conditional branches when using hardware performance counters

AMD Zen chips overcount conditional branches, by a few in tens of millions, due to a speculation optimization called SpecLockMap. The fix is setting a particular bit in the PMU MSR (model-specific register), which Rewind applies automatically, and which the rr debugger project also addresses, referenced in its issue rr#2034.

_Engineers tuning PMU-based tooling across CPU vendors can follow fixes like this one on daily.dev._

## Similar posts on daily.dev

- [Dafuq is a deterministic VM?](https://daily.dev/posts/dafuq-is-a-deterministic-vm--tkkdq96gu) · Farid Zakaria’s Blog · 0 upvotes · 0 comments
- [The fastest Linux timestamps · hmpc](https://daily.dev/posts/the-fastest-linux-timestamps-hmpc-evqoy4ob7) · Lobsters · 0 upvotes · 0 comments
- [Pushing the limits of RISC-V emulation](https://daily.dev/posts/pushing-the-limits-of-risc-v-emulation-dxh7xvq1d) · Hacker News · 0 upvotes · 0 comments
- [NDSS 2025 – CounterSEVeillance: Performance-Counter Attacks On AMD SEV-SNP](https://daily.dev/posts/ndss-2025-counterseveillance-performance-counter-attacks-on-amd-sev-snp-gqf73tije) · Security Boulevard · 1 upvotes · 0 comments

---

Tags: [#infrastructure](https://daily.dev/tags/infrastructure), [#hardware](https://daily.dev/tags/hardware)

[View this post on daily.dev](https://daily.dev/posts/a-clock-made-of-branches-bxrqnrnxg)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"A clock made of branches","url":"https://daily.dev/posts/a-clock-made-of-branches-bxrqnrnxg","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/a-clock-made-of-branches-bxrqnrnxg"},"datePublished":"2026-11-02T05:56:52.059Z","dateModified":"2026-11-02T05:57:23.298Z","description":"Rewind, a deterministic VM, needs a clock that behaves the same on every replay, so it can't use host wall-clock time. Its 'exit time' mode advances 5...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/0dfef443c85c53fff25cd5a5b1c63702?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/0dfef443c85c53fff25cd5a5b1c63702?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Farid Zakaria’s Blog","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Farid Zakaria’s Blog","logo":"https://media.daily.dev/image/upload/s--YqqvRt90--/f_auto/v1723789280/logos/fzakaria","url":"https://daily.dev/sources/fzakaria"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/a-clock-made-of-branches-bxrqnrnxg","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"infrastructure,hardware","timeRequired":"PT6M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Farid Zakaria’s Blog","item":"https://daily.dev/sources/fzakaria"},{"@type":"ListItem","position":3,"name":"A clock made of branches"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/a-clock-made-of-branches-bxrqnrnxg#faq","mainEntity":[{"@type":"Question","name":"why does the instruction count from perf stat vary between identical runs of the same program","acceptedAnswer":{"@type":"Answer","text":"Instruction counts drift because the CPU's instruction counter also captures interrupts from outside the program, such as timer ticks, network packet arrivals, inter-processor interrupts, and page faults. Running the same billion-iteration decrement loop twice showed instruction counts of 2,000,001,025 and 2,000,001,054, a difference tied almost exactly to the number of hardware interrupts the pinned CPU took during each run. daily.dev surfaces performance-counter deep dives for engineers debugging nondeterministic profiling results."}},{"@type":"Question","name":"how can I get a deterministic measurement of CPU time for record-replay debugging","acceptedAnswer":{"@type":"Answer","text":"Counting retired conditional branches gives a deterministic proxy for time, since this count stays identical across runs of the same program even when the instruction count drifts due to interrupts. The rr debugger popularized this technique, calling it 'deterministic time,' advancing a virtual clock by one nanosecond per conditional branch retired by the guest. Developers building replay or record-and-replay tooling track techniques like this one on daily.dev."}},{"@type":"Question","name":"why does AMD Zen overcount conditional branches when using hardware performance counters","acceptedAnswer":{"@type":"Answer","text":"AMD Zen chips overcount conditional branches, by a few in tens of millions, due to a speculation optimization called SpecLockMap. The fix is setting a particular bit in the PMU MSR (model-specific register), which Rewind applies automatically, and which the rr debugger project also addresses, referenced in its issue rr#2034. Engineers tuning PMU-based tooling across CPU vendors can follow fixes like this one on daily.dev."}}]}
```

