Skip to content

[improve][broker] Reuse dispatched entry list for release - #291

Open
lhotari wants to merge 1 commit into
lh-perfopt-dedup-producer-statefrom
lh-improve-send-release-list
Open

lhotari wants to merge 1 commit into
lh-perfopt-dedup-producer-statefrom
lh-improve-send-release-list

Conversation

@lhotari

@lhotari lhotari commented Sep 19, 2026

Copy link
Copy Markdown
Owner

Motivation

Every consumer write currently copies the dispatched entries into a second ArrayList solely so the write-completion listener can release them. The original dispatch list is already owned by the send operation and remains valid until completion, so modern clients pay for an unnecessary list object, backing array, and per-entry copy on every outbound batch. Subscription fanout multiplies this work.

Modifications

For clients that support batch messages, release non-null entries directly from the original dispatch list after the channel flush completes. Keep the separate release list for legacy clients, where an incompatible batch entry can be rejected and released before other entries are written.

The change preserves protocol output, write order, flush timing, and the existing rule that entries are released only after Netty completes the flush.

Verifying this change

A saturation scenario used 500 producer connections, one topic, twenty Key_Shared subscriptions, and ten consumers per subscription. Each run produced one million messages and verified every device sequence at every subscription.

Order Revision Producer rate Fanout deliveries Correctness
1 unchanged 32,934 msg/s 20,000,000 complete and ordered
2 this change 34,706 msg/s 20,000,000 complete and ordered
3 unchanged 30,956 msg/s 20,000,000 complete and ordered

The changed run was 8.6% above the arithmetic mean of the surrounding controls. All runs reported zero duplicate, out-of-order, or invalid messages.

An allocation profile confirmed that the sender's ArrayList allocation and its directly attributed Object[] backing-array allocation disappeared. Other Object[] allocations from Netty leak tracking and queue resizing were unaffected.

Validation:

  • ./gradlew :pulsar-broker:compileJava
  • ./gradlew quickCheck
  • fanout correctness and allocation profiling described above

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant