Skip to content

pool: fix scaled-down threads still processing tasks - #90

Merged
v01dstar merged 1 commit into
tikv:masterfrom
mittalrishabh:rish_thread
Apr 21, 2026
Merged

pool: fix scaled-down threads still processing tasks#90
v01dstar merged 1 commit into
tikv:masterfrom
mittalrishabh:rish_thread

Conversation

@mittalrishabh

@mittalrishabh mittalrishabh commented Mar 31, 2026

Copy link
Copy Markdown
Member

Issue #19498
When threads are scaled down, threads with ID > core_thread_count should go to sleep immediately. Previously, the park validation callback would still pop tasks from the queue, causing scaled-down threads to keep working instead of sleeping.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where worker threads continued processing work even after the thread pool was scaled down to a smaller number of active workers, ensuring they properly enter sleep mode when no longer needed.

When threads are scaled down, threads with ID > core_thread_count
should go to sleep immediately. Previously, the park validation
callback would still pop tasks from the queue, causing scaled-down
threads to keep working instead of sleeping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: rishabh mittal <rishabh.mittal@airbnb.com>
@coderabbitai

coderabbitai Bot commented Mar 31, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The Local<T>::pop_or_sleep method's park-loop predicate now checks whether a worker's ID exceeds the current core thread count immediately after marking as sleeping. If so, the thread stays sleeping without attempting to dequeue tasks, preventing scaled-down workers from popping work.

Changes

Cohort / File(s) Summary
Thread Pool Worker Scaling
src/pool/spawn.rs
Added early-exit condition in park-loop predicate to check if worker ID exceeds core thread count before attempting local queue pop.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A sleepy thread now rests with grace,
No more work steals its resting place,
Core counts reign with atomic might,
Scaled-down workers sleep just right! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'pool: fix scaled-down threads still processing tasks' directly and accurately describes the main change: fixing a bug where scaled-down threads were improperly processing tasks instead of sleeping.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/pool/spawn.rs (1)

332-336: Add a regression test for this scale-down edge case.

Please add a test that scales down while tasks are pending and verifies workers above core_thread_count do not dequeue until scaled up (or shutdown). This path is concurrency-sensitive and worth pinning with coverage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pool/spawn.rs` around lines 332 - 336, Add a concurrency regression test
that reproduces the scale-down edge case in spawn.rs: create a pool with more
workers than core_thread_count, submit several long-blocking tasks (use a
Barrier or channel to hold tasks), trigger a scale-down so some worker threads
have id > core_thread_count, then assert those higher-id workers do not dequeue
new tasks while scaled down by verifying the pending task queue size or an
Atomic counter remains unchanged; finally scale up or shutdown to release
blocked tasks and verify completion. Use synchronization primitives
(Barrier/oneshot channels/AtomicUsize) to deterministically control task
start/finish and reference the core_thread_count and id check in spawn.rs when
locating the worker loop to ensure the test pins this path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/pool/spawn.rs`:
- Around line 332-336: Add a concurrency regression test that reproduces the
scale-down edge case in spawn.rs: create a pool with more workers than
core_thread_count, submit several long-blocking tasks (use a Barrier or channel
to hold tasks), trigger a scale-down so some worker threads have id >
core_thread_count, then assert those higher-id workers do not dequeue new tasks
while scaled down by verifying the pending task queue size or an Atomic counter
remains unchanged; finally scale up or shutdown to release blocked tasks and
verify completion. Use synchronization primitives (Barrier/oneshot
channels/AtomicUsize) to deterministically control task start/finish and
reference the core_thread_count and id check in spawn.rs when locating the
worker loop to ensure the test pins this path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a6e1976-f990-4f81-8623-bec26b6e1138

📥 Commits

Reviewing files that changed from the base of the PR and between 9fcf102 and ba32394.

📒 Files selected for processing (1)
  • src/pool/spawn.rs

@mittalrishabh

Copy link
Copy Markdown
Member Author

/retest

1 similar comment
@mittalrishabh

Copy link
Copy Markdown
Member Author

/retest

Comment thread src/pool/spawn.rs
}
// If this thread is above core_thread_count, go to sleep
// without popping so scaled-down threads don't keep working.
if id > self.core.config.core_thread_count.load(Ordering::SeqCst) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you explain the requirement that need to let the thread park immediately instead of trying to drain the tasks in the local queue? I think in most scenario, the difference should be very small.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We use the TiKV thread pool auto-scaling feature and observed that under load, TiKV scales down the number of threads — but the yatp pool does not shrink because its threads are occupied draining the queue and unified read pool CPU remains higher than the number of active threads shown by TiKV

@v01dstar
v01dstar merged commit f3acdd2 into tikv:master Apr 21, 2026
27 of 31 checks passed
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.

3 participants