pool: park scaled-down workers on a queue that never drains - #96
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review. 📝 WalkthroughWalkthroughThe change adds queue deferral detection and uses it to park scaled-down workers before they pop tasks. A test verifies that a surplus worker parks while tasks remain queued. ChangesScaled-down worker parking
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: 🔵 Low · up to Scaled-down workers now stop taking ordinary queued work and park promptly, improving scale-in behavior. During a concurrent reduction, a worker may still begin one additional task after observing the previous worker limit, creating a bounded scheduling and resource-containment risk that should have explicit owner awareness or follow-up. Sequence Diagram(s)sequenceDiagram
participant WorkerThread
participant Local
participant LocalQueue
participant Runner
WorkerThread->>Local: should_park_before_pop()
Local->>LocalQueue: may_defer()
Local-->>WorkerThread: Return park decision
WorkerThread->>Runner: pause()
WorkerThread->>WorkerThread: pop_or_sleep(None)
WorkerThread->>Runner: resume()
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
`WorkerThread::pop` spins on the local queue and returns as soon as a task is ready, so `pop_or_sleep` -- the only place that checks `core_thread_count` -- is never reached while the queue is backed up. Scaling in then has no effect exactly when it is needed: under a sustained backlog every thread keeps running. Check before the spin-pop loop instead, so a worker above `core_thread_count` pauses and parks. Custom queues stay on the old path, since their `PopResult::Pending` deadline is only observed there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: rishabh mittal <mittalrishabh@gmail.com>
7dd6ef0 to
fc181d7
Compare
|
/retest |
WorkerThread::pop duplicated the pause/pop_or_sleep/resume trio in both branches. Use should_park_before_pop to select initial_retry_at instead, so a surplus worker skips the spin loop and parks with no deadline while the trio appears once. No behavior change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: rishabh mittal <mittalrishabh@gmail.com>
ae6ed26 to
81ec333
Compare
What is changed and how it works
WorkerThread::popspin-pops the local queue and returns as soon as a task is ready.pop_or_sleep— the only place that compares the worker id againstcore_thread_count— is therefore never reached while the queue has work in it.The result is that scaling in has no effect exactly when it is needed. Under a sustained backlog every worker keeps finding a task, so
scale_workers(n)lowerscore_thread_countbut the surplus threads never park. We saw this on a TiKV unified read pool: the pool reported 7 core threads while measuring 8.8 cores of CPU, with 7k–12k tasks queued continuously.This moves the check ahead of the spin-pop loop: a worker above
core_thread_countpauses and parks straight away. Once parked, the existing logic inpop_or_sleep'svalidatecallback keeps it asleep until it is back within the core count, andunpark_one's park-token filter already declines to wake it.Custom queues are exempt. Only
custom::LocalQueue::popcan returnPopResult::Pending, and that deadline is observed on the spin-pop path, so scaled-down workers on a custom queue keep the old behaviour (test_scaled_down_pending_timeout_wakes_core_workercovers it). TheSingleLevel/Multilevel/Priorityqueues convert throughOption<Pop<T>>and can never producePending.Check List
Tests
test_scaled_down_worker_parks_while_tasks_are_queued— a worker abovecore_thread_countfacing 8 queued tasks must park withhandle == 0. Without the fix it runs all 8.Side effects
core_thread_count, which are already meant to be idle.Summary by CodeRabbit
Bug Fixes
Tests