Skip to content

Fix CPU-pegging busy-spin in Stop()#180

Merged
andrewwormald merged 1 commit intomainfrom
fix/stop-busy-spin
Mar 10, 2026
Merged

Fix CPU-pegging busy-spin in Stop()#180
andrewwormald merged 1 commit intomainfrom
fix/stop-busy-spin

Conversation

@andrewwormald
Copy link
Collaborator

@andrewwormald andrewwormald commented Mar 10, 2026

Problem

Stop() polls process states in a tight for {} loop with no yield or sleep, consuming 100% of a CPU core during shutdown.

Why

In services with multiple workflows, this multiplies — each Stop() call pins a core until all goroutines exit.

Fix

Add a short sleep between poll iterations to yield the CPU while still shutting down promptly.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved system resource efficiency during process shutdown operations, reducing unnecessary overhead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

The change introduces a 10-millisecond sleep in the Stop method's loop when running processes are detected. Previously, the loop would spin tightly whilst rechecking the process count. The addition of the sleep reduces CPU overhead during the waiting period between iterations.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

This is a straightforward addition of a single sleep statement with minimal logic complexity. The change is homogeneous, affecting only one location, and introduces no structural modifications or conditional logic.

Poem

A rabbit hops through code so neat,
With 10 milliseconds—not a beat!
No spinning tight, we rest and wait,
The process loop runs at a kinder rate. 🐰⏱️

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix CPU-pegging busy-spin in Stop()' accurately and specifically describes the main change: addressing a busy-spin CPU consumption issue in the Stop() method by adding sleep between poll iterations.
Description check ✅ Passed The description clearly explains the problem (tight loop consuming 100% CPU), the impact (multiple workflows multiply the issue), and the solution (adding sleep between iterations), all directly related to the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/stop-busy-spin

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
workflow.go (1)

350-351: Prefer the workflow clock over wall-clock sleep.

Line 351 uses time.Sleep, which bypasses Workflow.clock and makes Stop() harder to drive deterministically in tests. Given this type already abstracts time through clock.Clock (and the interface provides Sleep(time.Duration)), it would be cleaner to sleep via the injected clock here too.

♻️ Proposed change
-		time.Sleep(10 * time.Millisecond)
+		w.clock.Sleep(10 * time.Millisecond)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workflow.go` around lines 350 - 351, The code uses time.Sleep(10 *
time.Millisecond) which bypasses the workflow's injected clock; replace that
call with the workflow clock's Sleep method (e.g., w.clock.Sleep(10 *
time.Millisecond) or wf.clock.Sleep(...)) so tests can drive time
deterministically via Workflow.clock; ensure the package still imports the clock
package as needed and remove or keep the time import accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@workflow.go`:
- Around line 350-351: The code uses time.Sleep(10 * time.Millisecond) which
bypasses the workflow's injected clock; replace that call with the workflow
clock's Sleep method (e.g., w.clock.Sleep(10 * time.Millisecond) or
wf.clock.Sleep(...)) so tests can drive time deterministically via
Workflow.clock; ensure the package still imports the clock package as needed and
remove or keep the time import accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7ae1797b-3bb5-414c-9566-35ae9e016407

📥 Commits

Reviewing files that changed from the base of the PR and between f4d926f and 08d2e35.

📒 Files selected for processing (1)
  • workflow.go

@andrewwormald andrewwormald merged commit 7e04032 into main Mar 10, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants