PersistentShell polling causes excessive CPU on WSL
NousResearch/hermes-agent · cluster 2784 · environments
Data as of
Nothing open on GitHub. Fix merged in #2996. Check it covers your case.
The short answer
0open issues
0open PRs
5items grouped
- Known?
- Yes. 5 related items grouped here, 2 issues already closed.
- Fix event
- A fix was merged to main in PR #2996. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
partially resolved, deciding PR #2996. That is separate from the fix event. - Still open
- Nothing open on GitHub.
A fixed 10ms poll interval in PersistentShellMixin causes excessive resource consumption and high CPU usage, particularly on WSL/WSL2. Multiple fixes propose replacing it with exponential backoff.
Open issues0
Open PRs0
Fixes on record
-
#2996 fix(shell): exponential backoff for persistent shell polling
files:
tools/environments/persistent_shell.py,tools/environments/ssh.pyShow the diff
-
tools/environments/persistent_shell.py@@ -40,7 +40,8 @@ def _execute_oneshot(self, command: str, cwd: str, *, def _cleanup_temp_files(self): ... _session_id: str = "" - _poll_interval: float = 0.01 + _poll_interval_start: float = 0.01 # initial poll interval (10ms) + _poll_interval_max: float = 0.25 # max poll interval (250ms) — reduces I/O for long commands @property def _temp_prefix(self) -> str: @@ -224,7 +225,7 @@ def _execute_persistent_locked(self, command: str, cwd: str, ) self._send_to_shell(ipc_script) deadline = time.monotonic() + timeout - poll_interval = self._poll_interval + poll_interval = self._poll_interval_start # starts at 10ms, backs off to 250ms while True: if is_interrupted(): @@ -256,6 +257,10 @@ def _execute_persistent_locked(self, command: str, cwd: str, break time.sleep(poll_interval) + # Exponential backoff: fast start (10ms) for quick commands, + # ramps up to 250ms for long-running commands — reduces I/O by 10-25x + # on WSL2 where polling keeps the VM hot and memory pressure high. + poll_interval = min(poll_interval * 1.5, self._poll_interval_max) output, exit_code, new_cwd = self._read_persistent_output() if new_cwd: -
tools/environments/ssh.py@@ -87,7 +87,7 @@ def _establish_connection(self): except subprocess.TimeoutExpired: raise RuntimeError(f"SSH connection to {self.user}@{self.host} timed out") - _poll_interval: float = 0.15 + _poll_interval_start: float = 0.15 # SSH: higher initial interval (150ms) for network latency @property def _temp_prefix(self) -> str:
-
2 PRs closed without merging
From the close comments: duplicate 1 · merged via another change 1
Closed issues · 2
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.34: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- environments
- Merged PRs
- #2996
- Closed issues
- 2
- Attempts
- 2 PRs closed without merging
- Fix link checked
- 25 Mar 2026. This confirmation is old and may be out of date (a revert or reopen would not have invalidated it here); re-verify.