Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,32 @@ public static TopicName get(String domain, String tenant, String namespace, Stri
return TopicName.get(name);
}

/**
* Get or create a TopicName from the cache.
*
* <p>Optimization over {@code computeIfAbsent}: avoids holding the ConcurrentHashMap bin-lock
* while constructing a new TopicName object. The construction (string splitting / parsing) is
* pure CPU work and can be done outside the lock. In the typical steady-state (cache hit) this
* method does a single volatile read via {@code get()} and returns immediately with no
* synchronization overhead.
*
* <p>In the cache-miss case, two threads racing on the same key may both construct a
* {@code TopicName} instance, but only one wins the {@code putIfAbsent} and the loser's
* instance is simply discarded. This is safe because {@code TopicName} is immutable and
* construction is cheap compared to the lock-contention / context-switch cost of
* {@code computeIfAbsent}.
*/
public static TopicName get(String topic) {
// Fast path: already cached — single volatile read, no lock.
TopicName tp = cache.get(topic);
if (tp != null) {
return tp;
}
return cache.computeIfAbsent(topic, k -> new TopicName(k));
// Slow path: construct outside the bin-lock to avoid blocking other threads.
TopicName newTp = new TopicName(topic);
TopicName existing = cache.putIfAbsent(topic, newTp);
// If another thread raced us and already inserted, use its instance (keeps identity stable).
return existing != null ? existing : newTp;
}

public static TopicName getPartitionedTopicName(String topic) {
Expand Down
Loading