Skip to content

[improve][broker] Avoid topic-wide deduplication lock - #287

Open
lhotari wants to merge 1 commit into
lh-perfopt-repl-snapshot-timestampfrom
lh-perfopt-dedup-producer-state
Open

lhotari wants to merge 1 commit into
lh-perfopt-repl-snapshot-timestampfrom
lh-perfopt-dedup-producer-state

Conversation

@lhotari

@lhotari lhotari commented Sep 19, 2026

Copy link
Copy Markdown
Owner

Motivation

Broker-side duplicate admission currently synchronizes on one map for the entire topic. Messages from different producers therefore contend on the same monitor before their managed-ledger adds are submitted. This becomes expensive when many producer connections publish to one topic even though sequence ordering only needs coordination between calls using the same producer name.

Modifications

Use the existing ConcurrentMap operations to update the highest pushed sequence ID with a putIfAbsent/conditional replace loop. Updates for one producer remain linearizable, including the brief overlap possible during a reconnect, while unrelated producers no longer serialize on a topic-wide monitor.

The replication-v2 path retains its existing synchronization because its ledger-ID and entry-ID values must be checked and updated as one pair. Snapshot, recovery, persistence, and inactive-producer cleanup retain the existing map representation and behavior.

Verifying this change

A focused JMH benchmark measured:

Case Topic-wide monitor Per-producer update Change
Single producer thread 41.1 ns/op 31.6 ns/op 23% faster
16 distinct producers 1,435.8 ns/op 114.3 ns/op 92% faster
16 callers sharing one producer 1,077.1 ns/op 1,743.7 ns/op 62% slower

The shared-producer case models an exceptional reconnect overlap. Normal operation has one active connection for a producer name, while distinct producer names are the case this change improves. Accepted updates allocate 24 bytes in both implementations; retries in the deliberately contended same-producer case raised the candidate to about 31 bytes/op.

A broker lock profile with 500 stable producers, one topic, and twenty Key_Shared subscriptions with ten consumers each attributed 22.46% of sampled lock-wait weight to the normal-producer deduplication monitor. The changed implementation had no samples on that monitor.

An unprofiled candidate was bracketed by runs of the unchanged implementation:

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

The candidate was 5.3% above the arithmetic mean of the two surrounding runs. The exact percentage is host-specific; the stronger evidence is the removal of a topic-wide monitor shared by unrelated producer names. Every run reported zero duplicate, out-of-order, or invalid messages.

Validation:

  • 24 focused broker deduplication tests
  • 32-thread same-producer admission race coverage
  • focused JMH benchmark with GC allocation profiling
  • ./gradlew quickCheck
  • ./gradlew spotlessCheck checkstyleMain checkstyleTest

@lhotari
lhotari force-pushed the lh-perfopt-dedup-producer-state branch from 4328dda to 23d4917 Compare September 19, 2026 16:34
@lhotari
lhotari changed the base branch from lh-perfopt-dedup-producer-state-base to lh-perfopt-repl-snapshot-timestamp September 19, 2026 16:34
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