Headless SDK-spawned CLI burns a constant ~33% CPU per session (futex/sched_yield spin) — still present in 2.1.220

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 2 comments · opened Aug 2, 2026

Summary

Every Claude Code process spawned via @anthropic-ai/claude-agent-sdk query() sustains a near-constant ~33% of one core for its entire lifetime. The percentage is essentially identical across concurrent instances and does not drop between tokens — strace shows the time goes to a futex/sched_yield busy-wait, not productive syscalls. This is the same fingerprint as #17142 (closed stale, unfixed) and the same syscall family as #34518.

Environment

  • @anthropic-ai/claude-agent-sdk 0.3.220 (bundled CLI 2.1.220, native binary claude-agent-sdk-linux-x64)
  • Headless server (no TTY): Ubuntu, kernel 6.x, 4 cores / 8 GB, Node 24
  • CLI spawned per job via SDK query() with settingSources: [], CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1, DISABLE_TELEMETRY=1

Observed

Per-process CPU sampled every 15 s from /proc (top-style, % of one core) while 1→3 concurrent coding sessions run:

| concurrency | per-process CPU | total |
|---|---|---|
| 1 | ~32% | 32% |
| 3 | 33–36% each | ~100% |

The flat per-instance value regardless of concurrency indicates a fixed-duty-cycle loop rather than on-demand work. Windows (win32-x64 binary, CLI 2.1.220) shows ~26%, so this is cross-platform.

strace (10 s, active session, CLI 2.1.220)

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 86.03    0.170188           9     18087       355 futex
  8.07    0.015956          26       611           epoll_pwait2
  4.54    0.008991           7      1255           sched_yield
  0.68    0.001340           6       207           write
  0.63    0.001241           2       438           pread64

~1,800 futex/sec + ~125 sched_yield/sec; productive write syscalls are <1% of the total. Older binary 2.1.202 shows the identical profile (16,771 futex / 88.4%), so this is not a recent regression in 2.1.220.

Expected

A session driving a single SSE stream should mostly block in epoll; thread-pool synchronization should not dominate syscall time. Ideally the wait strategy backs off (blocking futex wait) instead of yield-spinning.

Reproduction

  1. Spawn any session via the agent SDK on a headless Linux host.
  2. pid=$(pgrep -x claude | head -1); strace -c -p $pid for 10 s.
  3. Observe futex dominating syscall time and a steady ~33% CPU for the whole session.

References

  • #17142 — same 27–33% magnitude and same futex/sched_yield fingerprint (closed as stale, not fixed)
  • #34518 — idle-variant with the same syscall family (statm pread64 / sched_yield / futex)
  • oven-sh/bun#21081, oven-sh/bun#27490 — upstream Bun candidates for the spin behavior

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗