Skip to content

MINOR: Make rack lookups cheaper in SubscribedTopicDescriberImpl - #4

Closed
dajac wants to merge 2 commits into
trunkfrom
describer-rack-lookups
Closed

dajac wants to merge 2 commits into
trunkfrom
describer-rack-lookups

Conversation

@dajac

@dajac dajac commented Sep 17, 2026 •

Copy link
Copy Markdown
Owner

MINOR: Make SubscribedTopicDescriberImpl.racksForPartition cheaper

With rack awareness enabled, the uniform2 assignor asks the describer
for
the racks of every partition of every subscribed topic, 100,000 times
for
100,000 partitions. Each call looked the topic up in the metadata image,
built an ArrayList with its default capacity, and copied it into a
HashSet
which the caller then iterates. Measured with
ServerSideAssignorBenchmark
(uniform2, rack aware, 100,000 partitions), this describer path was 60
to
80% of the time that rack awareness adds to an assignment and about 30
MB
of the 31 to 40 MB it adds in allocation, the HashSet copy and its
iteration being the largest part.

  • SubscribedTopicDescriberImpl remembers the last topic looked up, so
    the
    partitions of a topic asked one after the other cost a single lookup
    in
    the image instead of one per partition. The memo is an immutable
    record
    replaced as a whole, so a racy read still gives a consistent answer.
  • racksForPartition returns a compact immutable set of the distinct
    racks,
    found by comparison since the replicas of a partition are in a handful
    of racks, instead of a HashSet copy.
  • KraftTopicMetadata.partitionRacks sizes its list to the replicas and
    does not go through a lambda per replica.

The SubscribedTopicDescriber interface is unchanged. The returned set is
now unmodifiable; the interface never promised a mutable set and the
in-tree callers only iterate it.

Allocation per rack aware assignment drops from 38.6 to 18.8 MB with
10,000 members and 1,000 topics and from 42.2 to 21.2 MB with 20 members
and 10,000 topics; the time drops by about 20% on both (13.3 to 10.6 ms
and 31.5 to 24.4 ms on STABLE, 17.2 to 13.8 ms and 41.6 to 33.3 ms on
FULL).

MINOR: Only remember the last topic for rack lookups in

SubscribedTopicDescriberImpl

The describer remembered the last topic looked up for both numPartitions
and racksForPartition. Assignors ask numPartitions once per topic, so
the entry never hits there and only costs an allocation per topic: about
240 KB per assignment for 10,000 topics, on the plain path that never
asks for racks. numPartitions now goes to the image directly and only
racksForPartition, which is asked once per partition, keeps the entry.
The lookup counts of SubscribedTopicMetadataTest follow.

Review PR on the fork. These two commits are independent of the uniform2
assignor and could go to trunk on their own; the numbers above were
measured with the rack aware uniform2 assignor, which asks for the racks
of every partition.

🤖 Generated with Claude Code

dajac and others added 2 commits September 17, 2026 10:03
With rack awareness enabled, the uniform2 assignor asks the describer for
the racks of every partition of every subscribed topic, 100,000 times for
100,000 partitions. Each call looked the topic up in the metadata image,
built an ArrayList with its default capacity, and copied it into a HashSet
which the caller then iterates. Measured with ServerSideAssignorBenchmark
(uniform2, rack aware, 100,000 partitions), this describer path was 60 to
80% of the time that rack awareness adds to an assignment and about 30 MB
of the 31 to 40 MB it adds in allocation, the HashSet copy and its
iteration being the largest part.

- SubscribedTopicDescriberImpl remembers the last topic looked up, so the
  partitions of a topic asked one after the other cost a single lookup in
  the image instead of one per partition. The memo is an immutable record
  replaced as a whole, so a racy read still gives a consistent answer.
- racksForPartition returns a compact immutable set of the distinct racks,
  found by comparison since the replicas of a partition are in a handful
  of racks, instead of a HashSet copy.
- KraftTopicMetadata.partitionRacks sizes its list to the replicas and
  does not go through a lambda per replica.

The SubscribedTopicDescriber interface is unchanged. The returned set is
now unmodifiable; the interface never promised a mutable set and the
in-tree callers only iterate it.

Allocation per rack aware assignment drops from 38.6 to 18.8 MB with
10,000 members and 1,000 topics and from 42.2 to 21.2 MB with 20 members
and 10,000 topics; the time drops by about 20% on both (13.3 to 10.6 ms
and 31.5 to 24.4 ms on STABLE, 17.2 to 13.8 ms and 41.6 to 33.3 ms on
FULL).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…icDescriberImpl

The describer remembered the last topic looked up for both numPartitions
and racksForPartition. Assignors ask numPartitions once per topic, so
the entry never hits there and only costs an allocation per topic: about
240 KB per assignment for 10,000 topics, on the plain path that never
asks for racks. numPartitions now goes to the image directly and only
racksForPartition, which is asked once per partition, keeps the entry.
The lookup counts of SubscribedTopicMetadataTest follow.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant