You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by "poorbarcode (via GitHub)" <gi...@apache.org> on 2024/07/18 17:14:43 UTC

[PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

poorbarcode opened a new pull request, #23052:
URL: https://github.com/apache/pulsar/pull/23052

   ### Motivation
   
   `LoadableCache.get` cost too many CPU resources
   
   [broker_cpu.html.txt](https://github.com/user-attachments/files/16278265/broker_cpu.html.txt)
   
   ```
   pulsar-io-4-20" #135 prio=5 os_prio=0 cpu=79326083.91ms elapsed=1465985.25s tid=0x00007f5bc40740b0 nid=0xe9 runnable  [0x00007f5ba51fd000]
      java.lang.Thread.State: RUNNABLE
   	at java.util.concurrent.ConcurrentLinkedQueue.offer(java.base@17.0.10/ConcurrentLinkedQueue.java:380)
   	at java.util.concurrent.ConcurrentLinkedQueue.add(java.base@17.0.10/ConcurrentLinkedQueue.java:283)
   	at com.google.common.cache.LocalCache$Segment.recordRead(LocalCache.java:2546)
   	at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2068)
   	at com.google.common.cache.LocalCache.get(LocalCache.java:4012)
   	at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4035)
   	at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5011)
   	at org.apache.pulsar.common.naming.TopicName.get(TopicName.java:81)
   	at org.apache.pulsar.common.naming.SystemTopicNames.isEventSystemTopic(SystemTopicNames.java:62)
   	at org.apache.pulsar.common.naming.SystemTopicNames.isSystemTopic(SystemTopicNames.java:86)
   	at org.apache.pulsar.common.topics.TopicList.lambda$filterSystemTopic$1(TopicList.java:65)
   	at org.apache.pulsar.common.topics.TopicList$$Lambda$2132/0x00007f5d049a4800.test(Unknown Source)
   	at java.util.stream.ReferencePipeline$2$1.accept(java.base@17.0.10/ReferencePipeline.java:178)
   	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(java.base@17.0.10/ArrayList.java:1625)
   	at java.util.stream.AbstractPipeline.copyInto(java.base@17.0.10/AbstractPipeline.java:509)
   	at java.util.stream.AbstractPipeline.wrapAndCopyInto(java.base@17.0.10/AbstractPipeline.java:499)
   	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(java.base@17.0.10/ReduceOps.java:921)
   	at java.util.stream.AbstractPipeline.evaluate(java.base@17.0.10/AbstractPipeline.java:234)
   	at java.util.stream.ReferencePipeline.collect(java.base@17.0.10/ReferencePipeline.java:682)
   	at org.apache.pulsar.common.topics.TopicList.filterSystemTopic(TopicList.java:66)
   	at org.apache.pulsar.broker.service.ServerCnx.lambda$handleGetTopicsOfNamespace$47(ServerCnx.java:2126)
   	at org.apache.pulsar.broker.service.ServerCnx$$Lambda$2129/0x00007f5d049b1c80.accept(Unknown Source)
   	at java.util.concurrent.CompletableFuture.uniAcceptNow(java.base@17.0.10/CompletableFuture.java:757)
   	at java.util.concurrent.CompletableFuture.uniAcceptStage(java.base@17.0.10/CompletableFuture.java:735)
   	at java.util.concurrent.CompletableFuture.thenAccept(java.base@17.0.10/CompletableFuture.java:2182)
   	at org.apache.pulsar.broker.service.ServerCnx.lambda$handleGetTopicsOfNamespace$49(ServerCnx.java:2123)
   	at org.apache.pulsar.broker.service.ServerCnx$$Lambda$2128/0x00007f5d049b1a38.apply(Unknown Source)
   	at java.util.concurrent.CompletableFuture.uniApplyNow(java.base@17.0.10/CompletableFuture.java:684)
   	at java.util.concurrent.CompletableFuture.uniApplyStage(java.base@17.0.10/CompletableFuture.java:662)
   	at java.util.concurrent.CompletableFuture.thenApply(java.base@17.0.10/CompletableFuture.java:2168)
   	at org.apache.pulsar.broker.service.ServerCnx.handleGetTopicsOfNamespace(ServerCnx.java:2120)
   	at org.apache.pulsar.common.protocol.PulsarDecoder.channelRead(PulsarDecoder.java:315)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
   	at io.netty.handler.flow.FlowControlHandler.dequeue(FlowControlHandler.java:202)
   	at io.netty.handler.flow.FlowControlHandler.channelRead(FlowControlHandler.java:164)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
   	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
   	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:333)
   	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:454)
   	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
   	at io.netty.handler.flush.FlushConsolidationHandler.channelRead(FlushConsolidationHandler.java:152)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
   	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
   	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
   	at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:800)
   	at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:509)
   	at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:407)
   	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
   	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
   	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
   	at java.lang.Thread.run(java.base@17.0.10/Thread.java:840)
   ```
   
   ### Modifications
   
   Because there is no need for a strict invalidate time, change the implementation to `ConcurrentHashMap`.
   
   
   
   #### Performance test
   After this PR: 
   - [test_merge_request.html.txt](https://github.com/user-attachments/files/16284759/test_merge_request.html.txt)
   
   
   ### Documentation
   
   <!-- DO NOT REMOVE THIS SECTION. CHECK THE PROPER BOX ONLY. -->
   
   - [ ] `doc` <!-- Your PR contains doc changes. -->
   - [ ] `doc-required` <!-- Your PR changes impact docs and you will update later -->
   - [x] `doc-not-needed` <!-- Your PR changes do not impact docs -->
   - [ ] `doc-complete` <!-- Docs have been already added -->
   
   ### Matching PR in forked repository
   
   PR in forked repository: x


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684183874


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   It is the same
   
   [new_test.html.txt](https://github.com/user-attachments/files/16310771/new_test.html.txt)
   
   ```java
   private static final LoadingCache<String, TopicName> cache =
   Caffeine.newBuilder().maximumSize(100_000).build(new CacheLoader<String, TopicName>() {
       @Override
       public TopicName load(String key) throws Exception {
           return new TopicName(key);
       }
   });
   ```
   
   ![WechatIMG164_](https://github.com/user-attachments/assets/ae580645-a20a-42f0-8d4a-a08995c16252)
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "BewareMyPower (via GitHub)" <gi...@apache.org>.
BewareMyPower commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683744928


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,13 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();
+
+    public static void clearIfReachedMaxCapacity(int maxCapacity) {
+        if (cache.size() > maxCapacity) {
+            cache.clear();

Review Comment:
   The performance of `LoadingCache` is bad because it maintains some other info. You can see the flame graph in this PR.
   
   When the cache size does not reach 100000, the performance of `ConcurrentHashMap#get` is 10x than `LoadingCache#get`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "BewareMyPower (via GitHub)" <gi...@apache.org>.
BewareMyPower commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683748328


##########
conf/broker.conf:
##########
@@ -159,6 +159,13 @@ skipBrokerShutdownOnOOM=false
 # Factory class-name to create topic with custom workflow
 topicFactoryClassName=
 
+# Max capacity of the topic name cache.
+topicNameCacheCaxCapacity=100000
+
+# A Specifies the minimum number of minutes that the system stays in the memory, to avoid clear cache frequently when
+# there are too many topics are in use.
+maxSecondsToClearTopicNameCache=7200

Review Comment:
   I don't suggest adding new configurations because it requires a PIP for that.
   
   Besides, I don't think there is much need to tune these two configs because we cannot predicate the actual use frequency of topic names.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "codelipenghui (via GitHub)" <gi...@apache.org>.
codelipenghui commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683939904


##########
conf/broker.conf:
##########
@@ -159,6 +159,13 @@ skipBrokerShutdownOnOOM=false
 # Factory class-name to create topic with custom workflow
 topicFactoryClassName=
 
+# Max capacity of the topic name cache. 0 means unlimited cache.

Review Comment:
   We'd better use -1 for unlimited cache and use 0 for no cache.



##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,13 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();
+
+    public static void clearIfReachedMaxCapacity(int maxCapacity) {
+        if (cache.size() > maxCapacity) {
+            cache.clear();

Review Comment:
   ConcurrentHashMap looks much better!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684161645


##########
pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java:
##########
@@ -625,6 +625,16 @@ public void start() throws Exception {
         this.updateBrokerDispatchThrottlingMaxRate();
         this.startCheckReplicationPolicies();
         this.startDeduplicationSnapshotMonitor();
+        this.startClearInvalidateTopicNameCacheTask();
+    }
+
+    protected void startClearInvalidateTopicNameCacheTask() {
+        final int maxSecondsToClearTopicNameCache = pulsar.getConfiguration().getMaxSecondsToClearTopicNameCache();
+        inactivityMonitor.scheduleAtFixedRate(
+            () -> TopicName.clearIfReachedMaxCapacity(pulsar.getConfiguration().getTopicNameCacheCaxCapacity()),
+            maxSecondsToClearTopicNameCache,
+            maxSecondsToClearTopicNameCache,
+            TimeUnit.SECONDS);

Review Comment:
   > This solution doesn't seem effective when the cache size can go over limits. I think it's better to use Caffeine cache with max size (as a LRU cache). You could remove expiration when using Caffeine if that's expensive.
   
   - Clearing cache is just for the topic that was deleted, if it was not deleted, leaving it in the memory is better.
   - Once there are too many topics in use, Caffeine will trigger queue items switching, which will cause more CPU costs.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684163168


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java:
##########
@@ -40,7 +40,7 @@ public class NamespaceName implements ServiceUnitId {
     private final String localName;
 
     private static final LoadingCache<String, NamespaceName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, NamespaceName>() {
+            .expireAfterWrite(30, TimeUnit.MINUTES).build(new CacheLoader<String, NamespaceName>() {

Review Comment:
   Removed this change



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "nodece (via GitHub)" <gi...@apache.org>.
nodece commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1685919714


##########
pulsar-broker/src/test/java/org/apache/pulsar/broker/PulsarServiceTest.java:
##########
@@ -187,6 +192,34 @@ public void testDynamicBrokerPort() throws Exception {
         assertEquals(pulsar.getWebServiceAddressTls(), "https://localhost:" + pulsar.getWebService().getListenPortHTTPS().get());
     }
 
+    @Test
+    public void testTopicCacheConfiguration() throws Exception {
+        cleanup();
+        setup();
+        assertEquals(conf.getTopicNameCacheCaxCapacity(), 5000);
+        assertEquals(conf.getMaxSecondsToClearTopicNameCache(), 5);
+
+        List<TopicName> topicNameCached = new ArrayList<>();
+        for (int i = 0; i < 20; i++) {
+            topicNameCached.add(TopicName.get("public/default/tp_" + i));
+        }
+
+        // Verify: the cache does not clear since it is not larger than max capacity.
+        Thread.sleep(10 * 1000);
+        for (int i = 0; i < 20; i++) {
+            assertTrue(topicNameCached.get(i) == TopicName.get("public/default/tp_" + i));
+        }
+
+        // Update max capacity.
+        admin.brokers().updateDynamicConfiguration("topicNameCacheCaxCapacity", "10");
+
+        // Verify: the cache were cleared.
+        Thread.sleep(10 * 1000);
+        for (int i = 0; i < 20; i++) {
+            assertFalse(topicNameCached.get(i) == TopicName.get("public/default/tp_" + i));

Review Comment:
   `TopicName.get` returns `null`?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "ben-manes (via GitHub)" <gi...@apache.org>.
ben-manes commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2241085367

   Thanks! I’ll look later today (it’s late my time). If you are running this on Mac/Windows then reading the current time is a system call, iirc. That’s much slower than a user space like Linux, so that can artificially skew your results my not being matching the deployment destination. The ticker is can be defined if truly necessary to optimize the clock reads.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "nodece (via GitHub)" <gi...@apache.org>.
nodece commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1685916983


##########
conf/broker.conf:
##########
@@ -159,6 +159,14 @@ skipBrokerShutdownOnOOM=false
 # Factory class-name to create topic with custom workflow
 topicFactoryClassName=
 
+# Max capacity of the topic name cache. -1 means unlimited cache; 0 means broker will clear all cache
+# per "maxSecondsToClearTopicNameCache", it does not mean broker will not cache TopicName.
+topicNameCacheCaxCapacity=100000

Review Comment:
   ```suggestion
   topicNameCacheMaxCapacity=100000
   ```
   
   Typo?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode merged PR #23052:
URL: https://github.com/apache/pulsar/pull/23052


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "ben-manes (via GitHub)" <gi...@apache.org>.
ben-manes commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1685279688


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -79,11 +78,7 @@ public static TopicName get(String domain, String tenant, String cluster, String
     }
 
     public static TopicName get(String topic) {
-        try {
-            return cache.get(topic);
-        } catch (ExecutionException | UncheckedExecutionException e) {
-            throw (RuntimeException) e.getCause();
-        }
+        return cache.computeIfAbsent(topic, k -> new TopicName(k));

Review Comment:
   computeIfAbsent is most often pessimistic in its locking, whereas Caffeine does a lock-free read first before falling back to a computation. Since caffeine is built on top of CHM and your readers will often block each other, something seems very amiss with your benchmark results being so vastly different in performance. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "lhotari (via GitHub)" <gi...@apache.org>.
lhotari commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684153134


##########
pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java:
##########
@@ -625,6 +625,16 @@ public void start() throws Exception {
         this.updateBrokerDispatchThrottlingMaxRate();
         this.startCheckReplicationPolicies();
         this.startDeduplicationSnapshotMonitor();
+        this.startClearInvalidateTopicNameCacheTask();
+    }
+
+    protected void startClearInvalidateTopicNameCacheTask() {
+        final int maxSecondsToClearTopicNameCache = pulsar.getConfiguration().getMaxSecondsToClearTopicNameCache();
+        inactivityMonitor.scheduleAtFixedRate(
+            () -> TopicName.clearIfReachedMaxCapacity(pulsar.getConfiguration().getTopicNameCacheCaxCapacity()),
+            maxSecondsToClearTopicNameCache,
+            maxSecondsToClearTopicNameCache,
+            TimeUnit.SECONDS);

Review Comment:
   This solution doesn't seem effective when the cache size can go over limits. I think it's better to use Caffeine cache with max size (as a LRU cache). You could remove expiration when using Caffeine if that's expensive. 



##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java:
##########
@@ -40,7 +40,7 @@ public class NamespaceName implements ServiceUnitId {
     private final String localName;
 
     private static final LoadingCache<String, NamespaceName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, NamespaceName>() {
+            .expireAfterWrite(30, TimeUnit.MINUTES).build(new CacheLoader<String, NamespaceName>() {

Review Comment:
   Why is this changed in this PR?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "lhotari (via GitHub)" <gi...@apache.org>.
lhotari commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2241094522

   > Thanks! I’ll look later today (it’s late my time). If you are running this on Mac/Windows then reading the current time is a system call, iirc. That’s much slower than a user space call like Linux, so that can artificially skew your results by not being matching the deployment destination. The ticker can be defined if truly necessary to optimize the clock reads.
   
   @BewareMyPower do you have a chance to run the benchmark on Linux?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2242528538

   Since @ben-manes and @lhotari did not answer, let me merge it first. We can improve the code continuously in the future.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1685786473


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -79,11 +78,7 @@ public static TopicName get(String domain, String tenant, String cluster, String
     }
 
     public static TopicName get(String topic) {
-        try {
-            return cache.get(topic);
-        } catch (ExecutionException | UncheckedExecutionException e) {
-            throw (RuntimeException) e.getCause();
-        }
+        return cache.computeIfAbsent(topic, k -> new TopicName(k));

Review Comment:
   Answered [here](https://github.com/apache/pulsar/pull/23052#issuecomment-2241487669)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "ben-manes (via GitHub)" <gi...@apache.org>.
ben-manes commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2241246130

   I'm not quite sure why expiration would have such a slowdown, but it is an expensive policy. Caffeine implements it in O(1) time, but calls to check if the retrieved entry has expired is usually the dominant cost. An unbounded ConcurrentHashMap is the baseline and the cache can only try to minimize the overhead of applying the eviction policies to that.
   
   The benchmark is single threaded, which means contention on computeIfAbsent won't be observed, and does not consume the return value, which allows for dead code elimination. These are probably not the root problem in them directly, but the full system benchmark still wouldn't make sense if you can do 5M ops/s per thread in the caches, assuming lock contention and clock sources were not a problem. Usually Guava suffers from contention (as shown in the original post), Caffeine doesn't, and if the same then it hints to the kernel clock source ([description](https://blog.packagecloud.io/system-calls-are-much-slower-on-ec2/)).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "lhotari (via GitHub)" <gi...@apache.org>.
lhotari commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684149229


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   It's not a fair comparison unless Caffeine is simply used as a LRU cache without expiration.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "codecov-commenter (via GitHub)" <gi...@apache.org>.
codecov-commenter commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2237423473

   ## [Codecov](https://app.codecov.io/gh/apache/pulsar/pull/23052?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
   All modified and coverable lines are covered by tests :white_check_mark:
   > Project coverage is 73.43%. Comparing base [(`bbc6224`)](https://app.codecov.io/gh/apache/pulsar/commit/bbc62245c5ddba1de4b1e7cee4ab49334bc36277?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) to head [(`083afe7`)](https://app.codecov.io/gh/apache/pulsar/commit/083afe7964b87bd72c11d8e38423bd908f38d1d9?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
   > Report is 456 commits behind head on master.
   
   <details><summary>Additional details and impacted files</summary>
   
   
   [![Impacted file tree graph](https://app.codecov.io/gh/apache/pulsar/pull/23052/graphs/tree.svg?width=650&height=150&src=pr&token=acYqCpsK9J&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)](https://app.codecov.io/gh/apache/pulsar/pull/23052?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   
   ```diff
   @@             Coverage Diff              @@
   ##             master   #23052      +/-   ##
   ============================================
   - Coverage     73.57%   73.43%   -0.14%     
   - Complexity    32624    33106     +482     
   ============================================
     Files          1877     1914      +37     
     Lines        139502   143649    +4147     
     Branches      15299    15671     +372     
   ============================================
   + Hits         102638   105495    +2857     
   - Misses        28908    30086    +1178     
   - Partials       7956     8068     +112     
   ```
   
   | [Flag](https://app.codecov.io/gh/apache/pulsar/pull/23052/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage Δ | |
   |---|---|---|
   | [inttests](https://app.codecov.io/gh/apache/pulsar/pull/23052/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `27.51% <75.00%> (+2.93%)` | :arrow_up: |
   | [systests](https://app.codecov.io/gh/apache/pulsar/pull/23052/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `24.72% <75.00%> (+0.40%)` | :arrow_up: |
   | [unittests](https://app.codecov.io/gh/apache/pulsar/pull/23052/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `72.48% <100.00%> (-0.36%)` | :arrow_down: |
   
   Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#carryforward-flags-in-the-pull-request-comment) to find out more.
   
   | [Files](https://app.codecov.io/gh/apache/pulsar/pull/23052?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage Δ | |
   |---|---|---|
   | [...org/apache/pulsar/broker/ServiceConfiguration.java](https://app.codecov.io/gh/apache/pulsar/pull/23052?src=pr&el=tree&filepath=pulsar-broker-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fpulsar%2Fbroker%2FServiceConfiguration.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-cHVsc2FyLWJyb2tlci1jb21tb24vc3JjL21haW4vamF2YS9vcmcvYXBhY2hlL3B1bHNhci9icm9rZXIvU2VydmljZUNvbmZpZ3VyYXRpb24uamF2YQ==) | `99.02% <100.00%> (-0.37%)` | :arrow_down: |
   | [...rg/apache/pulsar/broker/service/BrokerService.java](https://app.codecov.io/gh/apache/pulsar/pull/23052?src=pr&el=tree&filepath=pulsar-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fpulsar%2Fbroker%2Fservice%2FBrokerService.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-cHVsc2FyLWJyb2tlci9zcmMvbWFpbi9qYXZhL29yZy9hcGFjaGUvcHVsc2FyL2Jyb2tlci9zZXJ2aWNlL0Jyb2tlclNlcnZpY2UuamF2YQ==) | `82.09% <100.00%> (+1.31%)` | :arrow_up: |
   | [...org/apache/pulsar/common/naming/NamespaceName.java](https://app.codecov.io/gh/apache/pulsar/pull/23052?src=pr&el=tree&filepath=pulsar-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fpulsar%2Fcommon%2Fnaming%2FNamespaceName.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-cHVsc2FyLWNvbW1vbi9zcmMvbWFpbi9qYXZhL29yZy9hcGFjaGUvcHVsc2FyL2NvbW1vbi9uYW1pbmcvTmFtZXNwYWNlTmFtZS5qYXZh) | `89.04% <100.00%> (ø)` | |
   | [...ava/org/apache/pulsar/common/naming/TopicName.java](https://app.codecov.io/gh/apache/pulsar/pull/23052?src=pr&el=tree&filepath=pulsar-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fpulsar%2Fcommon%2Fnaming%2FTopicName.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-cHVsc2FyLWNvbW1vbi9zcmMvbWFpbi9qYXZhL29yZy9hcGFjaGUvcHVsc2FyL2NvbW1vbi9uYW1pbmcvVG9waWNOYW1lLmphdmE=) | `96.09% <100.00%> (+0.03%)` | :arrow_up: |
   
   ... and [496 files with indirect coverage changes](https://app.codecov.io/gh/apache/pulsar/pull/23052/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   
   </details>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "ben-manes (via GitHub)" <gi...@apache.org>.
ben-manes commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2241280440

   The expiration is a bit of a red haring because it forces the slower path of periodic maintenance, etc. The maximum size would too, except the benchmarks set that to be 10x the populated size and tracking only begins when it is 50% full. This is support if users decide to disable the configuration using an unreachable value, e.g. `Long.MAX_SIZE`, where we shouldn't prematurely allocate the policy history (a frequency histogram). When using `initialCapacity` to force a preallocation then the timings are relatively similar between expiration and maximum size in your benchmark. On my macbook, expiration is half the throughput due to calling the system clock, but when using `ticker(Ticker.disabledTicker())` then its only 20% slower.
   
   If adding concurrency to your tests, `@Threads(8)`, then the scaling is more pronounced on my macbook. A size-bounded cache significantly outperforms `testMapComputeIfAbsent` due to the locking (232M/s vs 14.5M/s), which is less pronounced after Java 9's improvements but can be severe if unlucky. When using expiration this drops to 6.5M/s and jumps to 121M/s if using a disabled ticker, showing that the macOS system call is the bottleneck. One could use an alternative time source, like a scheduled task to update a volatile field every second, to mimic Linux's userland approach. I think your benchmark is likely suffering the same system call overhead problem unless you can verify that it is vDSO mapped and that container virtualization is not interfering with it. Since this impacts all usages of the clock, e.g. for log events, it's probably worth checking your deployment target's behavior in case fixing the environment settings needs to be a a deployment step.
   
   The specialized cache should certainly be faster, but its unclear if periodically clearing it would cause a latency hiccup as all requests block trying to reload the entry. Since that's unbounded and stale topics are allowed, then it sounds like expiration isn't needed and that part of the performance analysis is moot? You could use a size bounded Caffeine cache without expiration and not worry about the clock source challenges. It's all kind of hard because benchmarks don't truly reflect real world system performance, so things like soft reference caches look wonderful in isolation and fail badly in practice, so it's all a tough juggling act.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "BewareMyPower (via GitHub)" <gi...@apache.org>.
BewareMyPower commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683747381


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,13 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();
+
+    public static void clearIfReachedMaxCapacity(int maxCapacity) {
+        if (cache.size() > maxCapacity) {
+            cache.clear();

Review Comment:
   Actually I've implemented my own `TopicName` locally. It does not use any cache, here are the test results.
   
   ```
   Benchmark                                    Mode  Cnt         Score         Error  Units
   TopicNameGetBenchmark.testCustomApi         thrpt    5   5218006.242 ±  110486.719  ops/s
   TopicNameGetBenchmark.testLoadingCache2Get  thrpt    5   6695534.090 ±  780412.049  ops/s
   TopicNameGetBenchmark.testLoadingCache3Get  thrpt    5  70196060.116 ± 1651256.265  ops/s
   TopicNameGetBenchmark.testLoadingCacheGet   thrpt    5   6437317.067 ±  600935.408  ops/s
   TopicNameGetBenchmark.testPulsarApi         thrpt    5   5958092.755 ±  150135.549  ops/s
   ```
   
   - `testCustomApi`: Parse the topic string every time without any cache
   - `testPulsarApi`: Parse the topic string only for the 1st time and read from the loading cache in the following tests
   
   As you can see, reading from the loading cache does not perform significantly better.
   
   <img width="1698" alt="image" src="https://github.com/user-attachments/assets/7fdf5cac-8032-4b56-9d39-133a2e6c871c">



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "BewareMyPower (via GitHub)" <gi...@apache.org>.
BewareMyPower commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2241080069

   Here is the benchmark's source code: https://github.com/BewareMyPower/CacheBenchmark
   
   A typical output:
   
   ```
   CacheReadBenchmark.testCaffine             thrpt    5   7432187.879 ±  746705.561  ops/s
   CacheReadBenchmark.testGuava               thrpt    5   6962764.989 ±  222299.106  ops/s
   CacheReadBenchmark.testMapComputeIfAbsent  thrpt    5  34219723.889 ±  686448.613  ops/s
   CacheReadBenchmark.testMapGet              thrpt    5  72643406.351 ± 1312709.392  ops/s
   ```
   
   The overhead for expiration seems significant. @ben-manes @lhotari Please help review if there is something wrong with it.
   
   The motivation is that the time cost of parsing a `TopicName` (with an efficient implementation, the current Pulsar implementation is inefficient) is just similar to getting the cached object from Guava `LoadingCache`.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "hangc0276 (via GitHub)" <gi...@apache.org>.
hangc0276 commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2242559506

   Good job! LGTM.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684183874


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   It is the same
   
   [new_test.html.txt](https://github.com/user-attachments/files/16310771/new_test.html.txt)
   
   ![WechatIMG164_](https://github.com/user-attachments/assets/ae580645-a20a-42f0-8d4a-a08995c16252)
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "lhotari (via GitHub)" <gi...@apache.org>.
lhotari commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683987203


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   Before making this change, please compare performance to Caffeine Cache which is a successor for Guava Cache ([benchmarks](https://github.com/ben-manes/caffeine/wiki/Benchmarks)). We use Caffeine on many locations in Pulsar.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "lhotari (via GitHub)" <gi...@apache.org>.
lhotari commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683987203


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   Before making this change, please compare performance to Caffeine Cache which is a successor for Guava Cache. We use Caffeine on many locations in Pulsar.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684097219


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   Done, updated in the Motivation



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2237113957

   /pulsarbot rerun-failure-checks


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2241487669

   @ben-manes @lhotari 
   
   The implementation of Caffeine without `expireAfterWrite/expireAfterAccess` is `com.github.benmanes.caffeine.cache.SSMS`, and it depends on `ConcurrentHashMap`<sup>see pictures below</sup>. So it can never be better than `ConcurrentHashMap`.
   
   **`get`**
   <img width="988" alt="Screenshot 2024-07-21 at 13 46 30" src="https://github.com/user-attachments/assets/8562afdd-2585-49e5-89a7-27d53e4b62b1">
   **`get -> load`**
   <img width="893" alt="Screenshot 2024-07-21 at 13 47 43" src="https://github.com/user-attachments/assets/940ec587-bfa6-432b-b794-ed7f6ed257f5">
   
   @BewareMyPower 
   
   Thanks for your testing, I think we'd better change the code like the one below(BTW, in my test, both implementations are close to each other)
   
   <img width="540" alt="Screenshot 2024-07-21 at 13 52 09" src="https://github.com/user-attachments/assets/2099a951-c203-49bf-a349-5b09a43ce569">
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684183874


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   It is the same
   
   [new_test.html.txt](https://github.com/user-attachments/files/16310771/new_test.html.txt)
   
   ```java
   private static final LoadingCache<String, TopicName> cache =
   Caffeine.newBuilder().maximumSize(100_000).build(new CacheLoader<String, TopicName>() {
       @Override
       public TopicName load(String key) throws Exception {
           return new TopicName(key);
       }
   });
   ```
   
   ![WechatIMG164_](https://github.com/user-attachments/assets/ae580645-a20a-42f0-8d4a-a08995c16252)
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "liangyepianzhou (via GitHub)" <gi...@apache.org>.
liangyepianzhou commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683716794


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,13 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();
+
+    public static void clearIfReachedMaxCapacity(int maxCapacity) {
+        if (cache.size() > maxCapacity) {
+            cache.clear();

Review Comment:
   Also, why can't we use a LoadingCache here?



##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,13 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();
+
+    public static void clearIfReachedMaxCapacity(int maxCapacity) {
+        if (cache.size() > maxCapacity) {
+            cache.clear();

Review Comment:
   Shouldn't we avoid clearing all the caches?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1685921400


##########
pulsar-broker/src/test/java/org/apache/pulsar/broker/PulsarServiceTest.java:
##########
@@ -187,6 +192,34 @@ public void testDynamicBrokerPort() throws Exception {
         assertEquals(pulsar.getWebServiceAddressTls(), "https://localhost:" + pulsar.getWebService().getListenPortHTTPS().get());
     }
 
+    @Test
+    public void testTopicCacheConfiguration() throws Exception {
+        cleanup();
+        setup();
+        assertEquals(conf.getTopicNameCacheCaxCapacity(), 5000);
+        assertEquals(conf.getMaxSecondsToClearTopicNameCache(), 5);
+
+        List<TopicName> topicNameCached = new ArrayList<>();
+        for (int i = 0; i < 20; i++) {
+            topicNameCached.add(TopicName.get("public/default/tp_" + i));
+        }
+
+        // Verify: the cache does not clear since it is not larger than max capacity.
+        Thread.sleep(10 * 1000);
+        for (int i = 0; i < 20; i++) {
+            assertTrue(topicNameCached.get(i) == TopicName.get("public/default/tp_" + i));
+        }
+
+        // Update max capacity.
+        admin.brokers().updateDynamicConfiguration("topicNameCacheCaxCapacity", "10");
+
+        // Verify: the cache were cleared.
+        Thread.sleep(10 * 1000);
+        for (int i = 0; i < 20; i++) {
+            assertFalse(topicNameCached.get(i) == TopicName.get("public/default/tp_" + i));

Review Comment:
   No, it will load the second time if there is no value cached



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "lhotari (via GitHub)" <gi...@apache.org>.
lhotari commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1684143477


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   What's the difference to Caffeine?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "BewareMyPower (via GitHub)" <gi...@apache.org>.
BewareMyPower commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2241147690

   @lhotari @ben-manes I ran the test on the `ubuntu-latest` GitHub Actions runner image. See results here https://github.com/BewareMyPower/CacheBenchmark/actions/runs/10020434100/job/27698014861
   
   ```
   Benchmark                                   Mode  Cnt         Score        Error  Units
   CacheReadBenchmark.testCaffine             thrpt   25   4895082.131 ± 308351.791  ops/s
   CacheReadBenchmark.testGuava               thrpt   25   4373360.896 ±  34218.258  ops/s
   CacheReadBenchmark.testMapComputeIfAbsent  thrpt   25  27010976.706 ± 590041.473  ops/s
   CacheReadBenchmark.testMapGet              thrpt   25  55345260.175 ± 462556.864  ops/s
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1685647755


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -54,13 +49,17 @@ public class TopicName implements ServiceUnitId {
 
     private final int partitionIndex;
 
-    private static final LoadingCache<String, TopicName> cache = CacheBuilder.newBuilder().maximumSize(100000)
-            .expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, TopicName>() {
-                @Override
-                public TopicName load(String name) throws Exception {
-                    return new TopicName(name);
-                }
-            });
+    private static final ConcurrentHashMap<String, TopicName> cache = new ConcurrentHashMap<>();

Review Comment:
   Sorry, I forgot to disable `enableBrokerSideSubscriptionPatternEvaluation` when I tested with `Caffeine` before. I finished a new test and updated the result in the Motivation.
   
   Summary:
   - `with expireAfterXxx` cost more CPU resources
   - `without expireAfterXxx` is close to `ConcurrentHashMap`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "merlimat (via GitHub)" <gi...@apache.org>.
merlimat commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683904834


##########
pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:
##########
@@ -79,11 +78,9 @@ public static TopicName get(String domain, String tenant, String cluster, String
     }
 
     public static TopicName get(String topic) {
-        try {
-            return cache.get(topic);
-        } catch (ExecutionException | UncheckedExecutionException e) {
-            throw (RuntimeException) e.getCause();
-        }
+        return cache.computeIfAbsent(topic, k -> {
+            return new TopicName(k);
+        });

Review Comment:
   ```suggestion
           return cache.computeIfAbsent(topic, k -> new TopicName(k));
   ```



##########
conf/broker.conf:
##########
@@ -159,6 +159,13 @@ skipBrokerShutdownOnOOM=false
 # Factory class-name to create topic with custom workflow
 topicFactoryClassName=
 
+# Max capacity of the topic name cache. 0 means unlimited cache.
+topicNameCacheCaxCapacity=100000
+
+# A Specifies the minimum number of minutes that the system stays in the memory, to avoid clear cache frequently when

Review Comment:
   ```suggestion
   # A Specifies the minimum number of seconds that the topic name stays in memory, to avoid clear cache frequently when
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "poorbarcode (via GitHub)" <gi...@apache.org>.
poorbarcode commented on code in PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#discussion_r1683975311


##########
conf/broker.conf:
##########
@@ -159,6 +159,13 @@ skipBrokerShutdownOnOOM=false
 # Factory class-name to create topic with custom workflow
 topicFactoryClassName=
 
+# Max capacity of the topic name cache. 0 means unlimited cache.

Review Comment:
   Maybe the following design is better:
   - `-1`: unlimited cache
   - `0`: broker clears all cache per `maxSecondsToClearTopicNameCache`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve] [broker] Improve CPU resources usege of TopicName Cache [pulsar]

Posted by "lhotari (via GitHub)" <gi...@apache.org>.
lhotari commented on PR #23052:
URL: https://github.com/apache/pulsar/pull/23052#issuecomment-2241093670

   > The overhead for expiration seems significant.
   
   @BewareMyPower to have a proper comparison with ConcurrentHashMap, could you also run a benchmark without expiration to measure the overhead of using Caffeine as a LRU cache? 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org