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.
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- Measure. Run
lf probe --json before.jsonwith the machine idle, and again under your real workload. - Find the source.
lf deviceslists 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. - Move it. Choose one option:
- No system change. Pin your own latency-critical thread to a quiet core with
SetThreadAffinityMaskorSetThreadSelectedCpuSets. 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.
- No system change. Pin your own latency-critical thread to a quiet core with
- Verify. Reboot, run
lf probe --json after.json, thenlf compare before.json after.json. If nothing improved, runlf 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.
| 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 |
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.
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.
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.
MIT