1.5 KiB
1.5 KiB
UNDF: UNDF-2026-000000505
pulsar-0001: GetTopicsResult.getTopics() — ArrayList.contains() inside dedup for loop
Defect ID
pulsar-0001
File:Line
pulsar-common/src/main/java/org/apache/pulsar/common/lookup/GetTopicsResult.java:117
Description
getTopics() deduplicates partitioned topic names:
List<String> grouped = new ArrayList<>();
for (String topic : nonPartitionedOrPartitionTopics) { // O(N)
String partitionedTopic = TopicName.get(topic).getPartitionedTopicName();
if (!grouped.contains(partitionedTopic)) { // O(N) linear scan
grouped.add(partitionedTopic);
}
}
grouped is an ArrayList<String>. Each .contains() is O(N). Total: O(N²).
This method is called on every consumer subscription lookup, broker topic listing,
and namespace topic query. For a namespace with 1,000 topic partitions (e.g.,
a topic with 1000 partitions), this scans up to 1000×1000 = 1M comparisons
instead of 1000 with a LinkedHashSet.
Complexity
- Slow: O(N²) — ArrayList.contains() = O(N)
- Fast: O(N) — LinkedHashSet.add() = O(1) with preserved insertion order
Severity
HIGH
Speedup Estimate
~N× improvement = 1000x at N=1000 partitions.
Fix
Replace ArrayList with LinkedHashSet<String> to preserve order while giving
O(1) dedup, then convert to List for the return type:
LinkedHashSet<String> grouped = new LinkedHashSet<>();
for (String topic : nonPartitionedOrPartitionTopics) {
grouped.add(TopicName.get(topic).getPartitionedTopicName());
}
topics = new ArrayList<>(grouped);