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

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #2996 fix(shell): exponential backoff for persistent shell polling

    merged to main

    files: tools/environments/persistent_shell.py, tools/environments/ssh.py

    Show 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

  • #2786 fix(shell): replace fixed 10ms poll interval with exponential backoff to reduce WSL2 resource consumption · merged via another change → #2996
  • #2787 fix(tools): exponential backoff for PersistentShellMixin poll interval · duplicate → #2786
Closed issues · 2
  • Closed#2784[Bug]: PersistentShellMixin 10ms poll interval causes excessive resource consumption on WSL
  • Closed#31513[WSL2] Gateway idle causes 100% CPU from wslhost on Windows 10
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.00 means 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 Lab

At 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.

For your agent

The same facts, typed.