This is an automated email from the ASF dual-hosted git repository.

lhotari pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new 3130a93b1ab [improve][broker] Improve the performance of TopicName 
constructor (#24463)
3130a93b1ab is described below

commit 3130a93b1abc053fc5e5c9687df044a6091d0a3c
Author: Yunze Xu <[email protected]>
AuthorDate: Tue Apr 21 19:08:11 2026 +0800

    [improve][broker] Improve the performance of TopicName constructor (#24463)
---
 .../org/apache/pulsar/common/naming/TopicName.java | 87 +++++++++++-----------
 1 file changed, 44 insertions(+), 43 deletions(-)

diff --git 
a/pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java 
b/pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java
index 83d694add67..52e9a60ad9b 100644
--- a/pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java
+++ b/pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java
@@ -120,41 +120,46 @@ public class TopicName implements ServiceUnitId {
         try {
             // The topic name can be in two different forms, one is fully 
qualified topic name,
             // the other one is short topic name
-            if (!completeTopicName.contains("://")) {
+            int index = completeTopicName.indexOf("://");
+            if (index < 0) {
                 // The short topic name can be:
                 // - <topic>
                 // - <tenant>/<namespace>/<topic>
-                String[] parts = StringUtils.split(completeTopicName, '/');
-                if (parts.length == 3) {
-                    completeTopicName = TopicDomain.persistent.name() + "://" 
+ completeTopicName;
-                } else if (parts.length == 1) {
-                    completeTopicName = TopicDomain.persistent.name() + "://"
-                        + PUBLIC_TENANT + "/" + DEFAULT_NAMESPACE + "/" + 
parts[0];
+                List<String> parts = splitBySlash(completeTopicName, 0);
+                this.domain = TopicDomain.persistent;
+                if (parts.size() == 3) {
+                    this.tenant = parts.get(0);
+                    this.namespacePortion = parts.get(1);
+                    this.localName = parts.get(2);
+                } else if (parts.size() == 1) {
+                    this.tenant = PUBLIC_TENANT;
+                    this.namespacePortion = DEFAULT_NAMESPACE;
+                    this.localName = parts.get(0);
                 } else {
                     throw new IllegalArgumentException(
                         "Invalid short topic name '" + completeTopicName + "', 
it should be in the format of "
                         + "<tenant>/<namespace>/<topic> or <topic>");
                 }
-            }
-
-            // Expected format: persistent://tenant/namespace/topic
-            List<String> parts = 
Splitter.on("://").limit(2).splitToList(completeTopicName);
-            this.domain = TopicDomain.getEnum(parts.get(0));
-
-            String rest = parts.get(1);
-
-            // Scalable topic domains (topic://, segment://) only support the 
new format
-            // and local names may contain '/', so use limit(3) to keep the 
rest as localName.
-            boolean isScalableDomain = this.domain == TopicDomain.topic
-                    || this.domain == TopicDomain.segment;
-            int splitLimit = isScalableDomain ? 3 : 4;
-            parts = Splitter.on("/").limit(splitLimit).splitToList(rest);
-            if (parts.size() == 4) {
-                throw new IllegalArgumentException(
-                        "V1 topic names (with cluster component) are no longer 
supported. "
-                        + "Please use the V2 format: 
'<domain>://tenant/namespace/topic'. Got: "
-                        + completeTopicName);
-            } else if (parts.size() == 3) {
+                this.segmentRange = null;
+                this.segmentId = -1;
+                this.completeTopicName = domain.name() + "://" + tenant + "/" 
+ namespacePortion + "/" + localName;
+            } else {
+                this.domain = 
TopicDomain.getEnum(completeTopicName.substring(0, index));
+                // Scalable topic domains (topic://, segment://) only support 
the new format
+                // and local names may contain '/', so use limit(3) to keep 
the rest as localName.
+                boolean isScalableDomain = this.domain == TopicDomain.topic
+                        || this.domain == TopicDomain.segment;
+                int splitLimit = isScalableDomain ? 3 : 4;
+                List<String> parts = 
splitBySlash(completeTopicName.substring(index + "://".length()),
+                        splitLimit);
+                if (parts.size() == 4) {
+                    throw new IllegalArgumentException(
+                            "V1 topic names (with cluster component) are no 
longer supported. "
+                                    + "Please use the V2 format: 
'<domain>://tenant/namespace/topic'. Got: "
+                                    + completeTopicName);
+                } else if (parts.size() != 3) {
+                    throw new IllegalArgumentException("Invalid topic name " + 
completeTopicName);
+                }
                 this.tenant = parts.get(0);
                 this.namespacePortion = parts.get(1);
                 String rawLocalName = parts.get(2);
@@ -165,8 +170,8 @@ public class TopicName implements ServiceUnitId {
                     if (lastSlash <= 0) {
                         throw new IllegalArgumentException(
                                 "Invalid segment topic name: local name must 
contain"
-                                + " 
'<parent-topic>/<hashStart>-<hashEnd>-<segmentId>'. Got: "
-                                + completeTopicName);
+                                        + " 
'<parent-topic>/<hashStart>-<hashEnd>-<segmentId>'. Got: "
+                                        + completeTopicName);
                     }
                     this.localName = rawLocalName.substring(0, lastSlash);
                     String descriptor = rawLocalName.substring(lastSlash + 1);
@@ -174,7 +179,7 @@ public class TopicName implements ServiceUnitId {
                     if (descParts.length != 3) {
                         throw new IllegalArgumentException(
                                 "Invalid segment descriptor: expected 
'<hexStart>-<hexEnd>-<segmentId>',"
-                                + " got: '" + descriptor + "'");
+                                        + " got: '" + descriptor + "'");
                     }
                     this.segmentRange = HashRange.of(
                             Integer.parseInt(descParts[0], 16),
@@ -186,28 +191,24 @@ public class TopicName implements ServiceUnitId {
                     this.segmentId = -1;
                 }
 
-                this.partitionIndex = getPartitionIndex(completeTopicName);
-                this.namespaceName = NamespaceName.get(tenant, 
namespacePortion);
-            } else {
-                throw new IllegalArgumentException("Invalid topic name: " + 
completeTopicName);
+                if (this.domain == TopicDomain.segment) {
+                    this.completeTopicName = String.format("%s://%s/%s/%s/%s",
+                            domain, tenant, namespacePortion, localName,
+                            String.format("%04x-%04x-%d", 
segmentRange.start(), segmentRange.end(), segmentId));
+                } else {
+                    this.completeTopicName = completeTopicName;
+                }
             }
 
             if (StringUtils.isBlank(localName)) {
                 throw new IllegalArgumentException(String.format("Invalid 
topic name: %s. Topic local name must not"
                         + " be blank.", completeTopicName));
             }
-
+            this.partitionIndex = getPartitionIndex(localName);
+            this.namespaceName = NamespaceName.get(tenant, namespacePortion);
         } catch (NullPointerException e) {
             throw new IllegalArgumentException("Invalid topic name: " + 
completeTopicName, e);
         }
-        if (this.domain == TopicDomain.segment) {
-            this.completeTopicName = String.format("%s://%s/%s/%s/%s",
-                    domain, tenant, namespacePortion, localName,
-                    String.format("%04x-%04x-%d", segmentRange.start(), 
segmentRange.end(), segmentId));
-        } else {
-            this.completeTopicName = String.format("%s://%s/%s/%s",
-                    domain, tenant, namespacePortion, localName);
-        }
     }
 
     public boolean isPersistent() {

Reply via email to