perf(server): stop Windows port discovery thrashing WMI - #6254
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a78e13b. Configure here.
ApprovabilityVerdict: Needs human review Performance optimization that changes the Windows PowerShell port probe to build a process-name map once and adds cooldown/single-flight mechanisms. While the changes are well-tested and focused, they modify core probing infrastructure with new state management, and the author is not a frequent contributor to this file. You can customize Macroscope's approvability policy. Learn more. |
e3f7e1b to
c74fb6b
Compare
…light Review: tick-based cool-off could be burned by retain/scan/poll, and overlapping scans could both spawn PowerShell before either armed the cooldown. Use a wall-clock cooldown deadline and claim single-flight ownership before spawning the listener probe.
|
Addressing issues found by macroscopeapp and cursor... will submit changes soon. |
|
Pushed a follow-up commit that addresses the Macroscope/Bugbot findings on the first commit:
Tests: |
Claiming the single-flight probe then attaching Effect.ensuring later left a window where interruption stuck windowsListenerProbeInFlight true forever. Bracket claim/use/release with acquireUseRelease and cover recovery after interrupt.
CDVolvik
left a comment
There was a problem hiding this comment.
Collapsing the per-listener Get-Process -Id into one map is clearly right, that was the quadratic part. Two things about the new gate though.
The cooldown only arms on timeout, and spawn failure is the case that repeats forever.
ProcessSpawnError: recoverWindowsProbeFailure,
...
ProcessTimeoutError: (error) =>
armWindowsListenerCooldown.pipe(Effect.zipRight(recoverWindowsProbeFailure(error))),A timeout is transient, and it gets the 60s cool-off. A spawn failure is usually not transient — powershell.exe blocked by policy, AppLocker, a stripped PATH — and it gets nothing, so the 3s poll retries the spawn indefinitely. That is a steadier drip of process creation than the timeout case this PR is fixing. Whatever the cool-off is worth after a timeout, it is worth more after a spawn error.
While skipping, the scan publishes the common-port list rather than holding the last snapshot.
skip returns null, and null falls through to probeCommonPorts(). So during the 60s cooldown, and during any single-flight overlap, every tick publishes only COMMON_DEV_PORTS instead of the real listener set. At a 3s interval that is roughly twenty ticks where a dev server on a non-common port drops out of the snapshot and then returns. Listeners see it as the server disappearing rather than as degraded discovery.
Returning state.lastSnapshot on skip would keep the last good answer instead of replacing it with a narrower one. That also makes the distinction meaningful: common ports as a genuine fallback when there is nothing better, last snapshot when there is.
Smaller notes:
Date.now()rather thanClockmeans the cooldown window cannot be driven byTestClock, so the 60s behaviour is hard to cover. The comment explains the wall-clock intent, andClock.currentTimeMillisis also wall-clock under the live layer, so it would keep the intent and stay testable.- The title says WMI, but
Get-NetTCPConnectionis still a CIM cmdlet, so the WMI round trip stays and only its frequency drops. Worth wording so nobody later reads this as WMI having been removed from the path. - The branch is currently CONFLICTING against main.
The acquireUseRelease comment explaining why it is not claim-plus-ensuring is a nice touch, that interrupt window is easy to miss.
|
Note 🤖 GPT-6 Astra (preview) responding on behalf of Theo This was closed as part of an automated cleanup pass. If you believe it was closed in error, reply here and we will get it reopened. Closing in favor of #9520, which replaces Windows PowerShell listener discovery with native enumeration. Review continues there, including Windows verification. That removes the polling path this branch tries to reduce. The listener PID mapping, interrupted scan recovery, and non-common-port fallback cases are recorded on the retained PR. |

Problem
On busy Windows machines, preview port discovery re-spawns a PowerShell listener probe every few seconds. The probe called
Get-Process -Idonce per listening socket, which often exceeded the 5s timeout. Timed-out probes were killed mid-WMI query and retried forever, driving sustained WMI/CPU load (#5900).Fix
Get-Processper probe instead of per connection.Verification
vp test run apps/server/src/preview/PortScanner.test.ts(6 passed)localhost:3000listener.Checklist
Model: Grok 4.5 · Harness: Grok Build / T3 Code
Note
Medium Risk
Changes Windows process probing and port discovery behavior; during cooldown or concurrent scans, results may omit process names via the common-port fallback.
Overview
Stops Windows preview port discovery from repeatedly spawning expensive PowerShell/WMI probes that were timing out and thrashing CPU (#5900).
Replaces per-listener
Get-Process -Idwith a singleWINDOWS_LISTENER_COMMANDthat builds the PID→name map once. Adds single-flight gating and a 60s wall-clock cooldown after timeouts so concurrentscan()/ poll / retain paths fall back to common ports instead of stacking probes. UsesacquireUseReleaseso the in-flight flag clears even if the probe fiber is interrupted.Reviewed by Cursor Bugbot for commit 920f825. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Stop Windows port discovery from thrashing WMI with per-listener
Get-ProcesscallsGet-Process -IdPowerShell calls with a single PID-to-name map built once per probe via the newWINDOWS_LISTENER_COMMANDin PortScanner.ts.scan()calls skip the probe and fall back to common-port results while the probe is in flight.WINDOWS_LISTENER_COOLDOWN_MS) after aProcessTimeoutErrorso subsequent scans skip PowerShell until the cooldown expires.acquireUseReleaseso fiber interruption cannot leave the gate permanently locked.Macroscope summarized 920f825.