Skip to content

Fix missing expired query callbacks and improve secondary workload queue thread wakeup - #19167

Open
adasari wants to merge 2 commits into
apache:masterfrom
adasari:adsaari/secondary-query-handling-improvements
Open

Fix missing expired query callbacks and improve secondary workload queue thread wakeup#19167
adasari wants to merge 2 commits into
apache:masterfrom
adasari:adsaari/secondary-query-handling-improvements

Conversation

@adasari

@adasari adasari commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Problems:

  1. The BinaryWorkloadScheduler dispatch thread polls SecondaryWorkloadQueue every 1 ms (default) regardless of whether any secondary queries exist. Secondary queries are not frequent, So on a server with no secondary queries, there are ~1000 needless wakeups per min, per server, on a Thread.MAX_PRIORITY daemon thread.
  2. Also, SecondaryWorkloadQueue removing expired queries without ever completing its result future. so the server never sent a response for it and leaked the entry tracking it.

Changes

  1. Problem#1: (perf improvement) (Changed BinaryWorkloadScheduler only to begin with, PriorityScheduler is untouched)
    • Untimed wait when the queue is empty. put() already signals _queryReaderCondition under _queueLock, so nothing else can make the queue non-empty without waking the reader. This eliminates 100% of idle wakeups.
    • Signal when reserved threads are released.
    • Timed wait retained when the queue is non-empty. The timed branch keeps that sweep running and now only ticks in the rare state where secondary queries are queued and the group is at its thread limit.
  2. Problem#2: (bug fix) (fixed for SecondaryWorkloadQueue only to begin with, MultiLevelPriorityQueue is untouched)
    • SchedulerGroup.trimExpired now returns the removed queries so the caller can complete them.
    • SecondaryWorkloadQueue takes a Consumer expiry handler and invokes it for each.

Testing:
Unit tests SecondaryWorkloadQueueTest

@adasari

adasari commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@yashmayya Could you review when you get a chance ? Please feel free to re-assign.

@yashmayya
yashmayya requested review from vvivekiyer and a lite review from Copilot August 5, 2026 22:11

Copilot AI left a comment

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.

Pull request overview

This PR improves the secondary-query scheduling path in pinot-core by (1) reducing idle wakeups in the secondary workload dispatch loop and (2) ensuring expired secondary queries are completed via a callback so their response futures don’t leak.

Changes:

  • Update SecondaryWorkloadQueue.take() to do an untimed wait when empty, and to return expired queries from trimExpired() for callback-based completion outside the queue lock.
  • Extend SchedulerGroup.trimExpired() to return the removed queries, enabling callers to complete their futures.
  • Wire expiry handling + worker-release signaling into BinaryWorkloadScheduler, and add unit tests validating ordering, expiry completion, and wakeup behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pinot-core/src/test/java/org/apache/pinot/core/query/scheduler/SecondaryWorkloadQueueTest.java New unit tests covering expiry completion, lock behavior, and wakeup signaling semantics.
pinot-core/src/main/java/org/apache/pinot/core/query/scheduler/SecondaryWorkloadQueue.java Adds expiry callback handling, eliminates idle timed polling when the queue is empty, and adds signalWorkersReleased().
pinot-core/src/main/java/org/apache/pinot/core/query/scheduler/SchedulerGroup.java Changes trimExpired() to return removed queries for completion by callers.
pinot-core/src/main/java/org/apache/pinot/core/query/scheduler/BinaryWorkloadScheduler.java Passes expiry handler into SecondaryWorkloadQueue and signals when workers are released.
pinot-core/src/main/java/org/apache/pinot/core/query/scheduler/AbstractSchedulerGroup.java Implements trimExpired() returning the removed expired queries.

Comment on lines 159 to 163
executorService.releaseWorkers();
schedulerGroup.endQuery();
_secondaryQueryQ.signalWorkersReleased();
_secondaryRunnerSemaphore.release();
checkStopResourceManager();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added query completion callback functionality when take return null i.e no query.

Comment on lines +174 to +182
/// Signals the reader that reserved threads were released, so canSchedule() may now pass.
public void signalWorkersReleased() {
_queueLock.lock();
try {
_queryReaderCondition.signal();
} finally {
_queueLock.unlock();
}
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

not worth changing? if the queue is empty, a waiting thread wakes, reacquires the lock, sees the queue is empty, and waits again.

@codecov-commenter

codecov-commenter commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 57.69231% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.60%. Comparing base (14333f3) to head (b811ed4).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
.../core/query/scheduler/BinaryWorkloadScheduler.java 5.88% 16 Missing ⚠️
...t/core/query/scheduler/SecondaryWorkloadQueue.java 83.33% 4 Missing and 1 partial ⚠️
...t/core/query/scheduler/AbstractSchedulerGroup.java 80.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #19167      +/-   ##
============================================
+ Coverage     66.57%   66.60%   +0.03%     
  Complexity     1423     1423              
============================================
  Files          3441     3441              
  Lines        218320   218365      +45     
  Branches      34737    34745       +8     
============================================
+ Hits         145341   145437      +96     
+ Misses        61251    61205      -46     
+ Partials      11728    11723       -5     
Flag Coverage Δ
custom-integration1 100.00% <ø> (ø)
integration 100.00% <ø> (ø)
integration1 100.00% <ø> (ø)
integration2 0.00% <ø> (ø)
java-25 66.60% <57.69%> (+0.03%) ⬆️
temurin 66.60% <57.69%> (+0.03%) ⬆️
unittests 66.59% <57.69%> (+0.03%) ⬆️
unittests1 57.16% <57.69%> (+0.04%) ⬆️
unittests2 38.88% <0.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Jackie-Jiang Jackie-Jiang added bug Something is not working as expected query Related to query processing labels Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something is not working as expected query Related to query processing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants