Skip to content

Keep one idle worker spinning instead of sleeping - #8036

Open
hkaiser wants to merge 2 commits into
local-priority-tunedfrom
scheduler-idle-sentinel-pr
Open

hkaiser wants to merge 2 commits into
local-priority-tunedfrom
scheduler-idle-sentinel-pr

Conversation

@hkaiser

@hkaiser hkaiser commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

In fast idle mode an idle worker spins for short backoff periods and sleeps for longer ones. A new thread that finds all idle workers asleep waits for a wake up, which takes a few microseconds on Linux and a millisecond or more on Windows. With strictly periodic work the backoff can also lock into one phase against it, which makes a whole process fast or slow.

With this, a worker that would go to sleep becomes the sentinel if there is none, and spins through its period instead. It looks at its own queues every round, and at the queues it steals from right after a thread was queued anywhere (wake_one, wake_if_sleeping and do_some_work count the new threads while there is a sentinel; the sentinel and the count share one cache line). The sentinel isn't counted as a spinning worker, so a worker that queues small threads for itself still wakes up a sleeper. Its spin is out of line in spin_as_sentinel. One idle core stays busy while the pool is idle; normal mode is not changed.

Based on #8035.

Measured on top of #8018, against it (two sessions per mode with interleaved builds, a row counts only if it moves by more than 3% with p < 0.05 in the same direction in both sessions):

  • Windows (MSVC): level in normal mode. In fast idle mode the timer tail goes: the p99 of small tasks posted to a busy worker at 4 workers drops from 14 ms to 41 us. Batch medians at 4 workers drop to 0.61 and the medians of bursts of tiny tasks to 0.71 to 0.89. No latency row loses. The cost is up to one more busy core at low load.
  • 2 x Xeon Gold 6148 (GCC 14.2), fast idle mode: batch medians at 4 workers 0.77, burst medians at 4 and 16 workers 0.41 to 0.55, the p99 of sparse small tasks at 4 workers 0.34. Slower: the burst medians at 32 workers (1.37 to 1.47) and the sparse medians at 16 and 32 workers (1.04 to 1.20). About one more busy core at low load. In normal mode, where the sentinel never runs, its cache line moves placement rows by 3 to 14% either way in the sessions; over 16 heap layouts it is within 2% of Use task sizes to wake up workers in the local priority queue scheduler #8018.
  • DGX Spark (GCC 16.2), 10 workers: level in normal mode. In fast idle mode the medians of batches 0.90 to 0.94 and of sparse sized work 0.41 to 0.45; small sparse rows 6 to 8% slower. With periodic posts at 4 workers, the backoff no longer locks into a slow phase: the sparse medians with random gaps are 1.06 to 1.15 us instead of 4.06 us.

On top of #8035 (the same code in idle_callback_with_rules) the sentinel keeps the tuned scheduler's branch level with the sentinel branch on the DGX Spark, and on the Xeon with #8034 applied to both.

In fast idle mode an idle worker backs off: it spins for short periods and
sleeps for longer ones until it is woken up or its period ends. A new
thread that finds all idle workers asleep waits for a wake up, which takes
a few microseconds on Linux and up to the resolution of the timer, a
millisecond or more, on Windows. With strictly periodic work the backoff
can also lock into one phase against it, which makes a whole process fast
or slow.

A worker that would go to sleep now becomes the sentinel if there is none,
and spins through the period instead. It looks at its own queues every
round, and at the queues it steals from right after a thread was queued
anywhere: wake_one, wake_if_sleeping and do_some_work count the new threads
while there is a sentinel. Both the sentinel and the count are on one cache
line. The sentinel isn't counted as a spinning worker, so a worker that
queues small threads for itself still wakes up a sleeper. One idle core
stays busy while the pool is idle. Normal mode is not changed.

Signed-off-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>
Describe the idle worker that spins instead of sleeping in the idle
backoff section of the scheduler configuration guide.

Signed-off-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>
@coderabbitai

coderabbitai Bot commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 61f2b31d-bfbe-46c9-acf6-9bc5b44b5860

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant