Skip to content

About

Find and fix the rare long stalls Windows puts in front of latency-sensitive threads: per-core stall probe, interrupt affinity, MSI mode, ReservedCpuSets — with snapshots and exact undo.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

LatencyForge

Find and fix the rare, long stalls that Windows puts in front of latency-sensitive threads. Typical victims are input automation, audio, capture, and timing loops.

A busy-wait loop can be accurate to about 1 µs and still miss by 1–10 ms now and then. On modern Windows that tail almost never comes from the timer. It comes from the CPU core: interrupt handlers and DPCs from the GPU, USB, network, and storage drivers, SMIs from firmware, and C-state wake-ups. These all land on specific cores. LatencyForge shows you which cores they are, then helps you move the work off them, with a snapshot and one-command undo for every change.

> lf probe          (example output, Ryzen 9 7945HX)
 cpu  core  eff   >50µs/s  >200µs/s    max µs
   0     0    0       656        36      1123  NOISY ████████████
   1     0    0         0         0        28        ███
  ...
  24    12    0       340        22     10012  NOISY ██████████████████
  25    12    0         0         0        17        █
Noisy: CPU 0, 24. Quiet cores' longest stall: 168 µs.

Install

You need Windows 10 2004+ or Windows 11 and the .NET 8 SDK.

git clone https://github.com/NotBadSlime/LatencyForge
cd LatencyForge
dotnet run --project src/LatencyForge.Cli -c Release -- help
# or publish a single exe:
dotnet publish src/LatencyForge.Cli -c Release -r win-x64 --self-contained -p:PublishSingleFile=true -o dist

Workflow

  1. Measure. Run lf probe --json before.json with the machine idle, and again under your real workload.
  2. Find the source. lf devices lists the interrupt policy and MSI mode of your GPU, USB, network, audio, and storage controllers. LatencyMon or WPA (xperf -on PROC_THREAD+LOADER+DPC+INTERRUPT) tell you which driver is behind a noisy core.
  3. Move it. Choose one option:
    • No system change. Pin your own latency-critical thread to a quiet core with SetThreadAffinityMask or SetThreadSelectedCpuSets. Try this first. MacroHID does it automatically.
    • Route that device's interrupts elsewhere: lf affinity "RTX 4090" 2-3.
    • Turn on MSI where the driver supports it: lf msi "Realtek" on.
    • Keep the scheduler away from a core and reserve it for your thread: lf reserve 30-31.
  4. Verify. Reboot, run lf probe --json after.json, then lf compare before.json after.json. If nothing improved, run lf restore <id>.

Every tuning command only previews unless you add --apply. --apply needs an administrator console. It writes a snapshot to %ProgramData%\LatencyForge\snapshots before touching the registry, and rolls back if any write fails. lf snapshots lists the snapshots and lf restore <id> puts back the exact previous values, including deleting values that did not exist before.

Commands

Command Admin Changes system
lf probe [--window-ms 500] [--passes 3] [--cpus 0-7] [--json f] no no
lf compare before.json after.json no no
lf topology no no
lf devices [--all] no no
lf power no no
lf affinity <device> <cpus|default> [--apply] for --apply registry, after reboot
lf msi <device> on|off [--apply] for --apply registry, after reboot
lf reserve <cpus|none> [--apply] for --apply registry, after reboot
lf snapshots, lf restore <id> restore: yes restore: yes

How the probe works and what it can't see

For each logical processor, the probe pins a THREAD_PRIORITY_HIGHEST thread to it, spins on QueryPerformanceCounter for the window, and records every gap between consecutive reads. A gap means the thread was not running there: an ISR or DPC ran, an SMI fired, or a higher-priority thread preempted it. A core is noisy when, in at least half the passes, it shows ≥ 100 gaps over 50 µs per second, ≥ 20 over 200 µs per second, or any gap ≥ 2 ms. These thresholds come from a Ryzen 9 7945HX. See docs/research.md.

The probe only observes a core while it spins there, and it can't attribute a gap to a specific driver. Use LatencyMon or WPA for attribution. It is a user-mode measurement of exactly what your own thread would experience, which is the number that matters for user-mode timing.

Safety

Read docs/safety.md before using --apply. In short: changes to interrupt affinity and MSI are per device and documented by Microsoft, but a wrong MSI setting can stop a device from starting. ReservedCpuSets is undocumented on desktop Windows. Every change can be undone with lf restore, from Safe Mode if needed.

Relation to MacroHID

LatencyForge started as the system-level half of MacroHID's precision work. MacroHID measures cores in-process and avoids noisy ones without changing the system. LatencyForge is for people who want to change the system itself.

License

MIT

About

Find and fix the rare long stalls Windows puts in front of latency-sensitive threads: per-core stall probe, interrupt affinity, MSI mode, ReservedCpuSets — with snapshots and exact undo.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages