[improve][client] Coalesce message listener drain scheduling - #26531
Merged
lhotari merged 2 commits intoSep 14, 2026
Conversation
Reuse a per-consumer scheduler and coalesce burst notifications on the internal serial executor. Queue follow-up drains behind pending arrivals, and reset scheduling state on drain failures and rejected submissions. Add scheduler regression tests and a JMH scheduling benchmark. Assisted-by: Codex
void-ptr974
reviewed
Sep 11, 2026
…ures Request a later FIFO drain when listener submission fails after dequeuing a message. Add deterministic regression coverage for repeated rejection, bounded completion when every submission rejects, and pending arrivals. Assisted-by: Codex
void-ptr974
approved these changes
Sep 12, 2026
dao-jun
approved these changes
Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Each consumer message-listener notification currently allocates and submits a drain task to the internal executor. One task can drain multiple messages, so bursts also queue redundant tasks and executor queue nodes.
Modifications
ListenerTaskSchedulerthat reuses one drain task and coalesces notifications with atomic idle/scheduled/triggered-again states.finally, including after drain failures. Propagate submission rejection and reset state so a later notification can retry. Delivery is not guaranteed while the executor rejects work.The atomic reset separates the races: a trigger before the reset marks the state for a follow-up; a trigger after it schedules a task itself or merges with the follow-up. A race may cause an extra empty drain, but does not discard a notification on an accepting executor.
Verifying this change
The added tests cover arrivals queued behind a drain, burst coalescing, return to idle, notifications during draining, exceptions with and without pending notifications, rejection of initial and follow-up submissions, and five concurrent runs of four producers with 5,000 arrivals each. Existing consumer close/seek, listener ordering, partitioned and Shared/Key_Shared subscription, and custom listener-executor tests are also included in scoped validation.
Historical E020 measurements (not a new benchmark run for this extraction):
JMH used Corretto 25, ZGC with a 1 GiB heap, two forks, three 1-second warmups, five 1-second measurements and the GC profiler. The benchmark models queued arrivals and drains with a real
LinkedBlockingQueue; it excludes OS thread handoff, decoding and application callbacks. Coalescing improves bursts but adds about 10 ns for an isolated notification.A historical four-Shared-consumer profiling comparison estimated consumer allocation at 11.264 -> 10.498 GB (-6.8%) and executor queue-node allocation at 1.917 -> 1.487 GB (-22.4%). Throughput and CPU samples were essentially flat; zero failed ACKs were reported. These are sampled allocation estimates from single integration runs, with allocation-site variability and host temperatures reaching 100 C, so they do not establish a general throughput or CPU improvement. Raw profiles and adjacent Jafar analyses remain in the experiment archive; no new full profiling run was performed for this extraction.
Local validation passed:
./gradlew spotlessCheck checkstyleMain checkstyleTest,:microbench:compileJava, and 28 scoped test executions (12 scheduler, 2 consumer close/seek, 9 listener/ordering/Shared/partitioned, 4 Key_Shared ordering and 1 custom executor). No failures or skips; retries disabled with-PtestRetryCount=0, using--max-workers=2 --no-parallel.Does this pull request potentially affect one of the following parts: