You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2020/02/04 05:40:36 UTC

[dubbo] branch master updated: [Dubbo-perf]: Reduce object allocation for ProtocolUtils.serviceKey(int, String, String, String) (#5525)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new c0d62ed  [Dubbo-perf]: Reduce object allocation for ProtocolUtils.serviceKey(int, String, String, String) (#5525)
c0d62ed is described below

commit c0d62ed7a83347fa469c2b2a7d75287a5feb799b
Author: LinShunKang <li...@gmail.com>
AuthorDate: Tue Feb 4 13:39:48 2020 +0800

    [Dubbo-perf]: Reduce object allocation for ProtocolUtils.serviceKey(int, String, String, String) (#5525)
---
 .../dubbo/rpc/support/GroupServiceKeyCache.java    | 71 ++++++++++++++++++++
 .../apache/dubbo/rpc/support/ProtocolUtils.java    | 23 ++++---
 .../dubbo/rpc/support/ProtocolUtilsTest.java       | 75 ++++++++++++++++++++++
 3 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/GroupServiceKeyCache.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/GroupServiceKeyCache.java
new file mode 100644
index 0000000..3b37b59
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/GroupServiceKeyCache.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.support;
+
+import org.apache.dubbo.common.utils.StringUtils;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class GroupServiceKeyCache {
+
+    private final String serviceGroup;
+
+    //ConcurrentMap<serviceName, ConcurrentMap<serviceVersion, ConcurrentMap<port, String>>>
+    private final ConcurrentMap<String, ConcurrentMap<String, ConcurrentMap<Integer, String>>> serviceKeyMap;
+
+    public GroupServiceKeyCache(String serviceGroup) {
+        this.serviceGroup = serviceGroup;
+        this.serviceKeyMap = new ConcurrentHashMap<>(512);
+    }
+
+    public String getServiceKey(String serviceName, String serviceVersion, int port) {
+        ConcurrentMap<String, ConcurrentMap<Integer, String>> versionMap = serviceKeyMap.get(serviceName);
+        if (versionMap == null) {
+            serviceKeyMap.putIfAbsent(serviceName, new ConcurrentHashMap<>());
+            versionMap = serviceKeyMap.get(serviceName);
+        }
+
+        serviceVersion = serviceVersion == null ? "" : serviceVersion;
+        ConcurrentMap<Integer, String> portMap = versionMap.get(serviceVersion);
+        if (portMap == null) {
+            versionMap.putIfAbsent(serviceVersion, new ConcurrentHashMap<>());
+            portMap = versionMap.get(serviceVersion);
+        }
+
+        String serviceKey = portMap.get(port);
+        if (serviceKey == null) {
+            serviceKey = createServiceKey(serviceName, serviceVersion, port);
+            portMap.put(port, serviceKey);
+        }
+        return serviceKey;
+    }
+
+    private String createServiceKey(String serviceName, String serviceVersion, int port) {
+        StringBuilder buf = new StringBuilder();
+        if (StringUtils.isNotEmpty(serviceGroup)) {
+            buf.append(serviceGroup).append('/');
+        }
+
+        buf.append(serviceName);
+        if (StringUtils.isNotEmpty(serviceVersion) && !"0.0.0".equals(serviceVersion)) {
+            buf.append(':').append(serviceVersion);
+        }
+        buf.append(':').append(port);
+        return buf.toString();
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/ProtocolUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/ProtocolUtils.java
index 769a6a6..801132f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/ProtocolUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/ProtocolUtils.java
@@ -19,6 +19,9 @@ package org.apache.dubbo.rpc.support;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.StringUtils;
 
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_RAW_RETURN;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_BEAN;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_DEFAULT;
@@ -29,6 +32,8 @@ import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
 
 public class ProtocolUtils {
 
+    private static final ConcurrentMap<String, GroupServiceKeyCache> groupServiceKeyCacheMap = new ConcurrentHashMap<>();
+
     private ProtocolUtils() {
     }
 
@@ -38,19 +43,13 @@ public class ProtocolUtils {
     }
 
     public static String serviceKey(int port, String serviceName, String serviceVersion, String serviceGroup) {
-        StringBuilder buf = new StringBuilder();
-        if (StringUtils.isNotEmpty(serviceGroup)) {
-            buf.append(serviceGroup);
-            buf.append("/");
-        }
-        buf.append(serviceName);
-        if (serviceVersion != null && serviceVersion.length() > 0 && !"0.0.0".equals(serviceVersion)) {
-            buf.append(":");
-            buf.append(serviceVersion);
+        serviceGroup = serviceGroup == null ? "" : serviceGroup;
+        GroupServiceKeyCache groupServiceKeyCache = groupServiceKeyCacheMap.get(serviceGroup);
+        if (groupServiceKeyCache == null) {
+            groupServiceKeyCacheMap.putIfAbsent(serviceGroup, new GroupServiceKeyCache(serviceGroup));
+            groupServiceKeyCache = groupServiceKeyCacheMap.get(serviceGroup);
         }
-        buf.append(":");
-        buf.append(port);
-        return buf.toString();
+        return groupServiceKeyCache.getServiceKey(serviceName, serviceVersion, port);
     }
 
     public static boolean isGeneric(String generic) {
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/support/ProtocolUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/support/ProtocolUtilsTest.java
new file mode 100644
index 0000000..eaed8c8
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/support/ProtocolUtilsTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.support;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class ProtocolUtilsTest {
+
+    @Test
+    public void testGetServiceKey() {
+        final String serviceName = "com.abc.demoService";
+        final int port = 1001;
+
+        assertServiceKey(port, serviceName, "1.0.0", "group");
+        assertServiceKey(port, serviceName, "1.0.0", "");
+        assertServiceKey(port, serviceName, "1.0.0", null);
+
+        assertServiceKey(port, serviceName, "0.0", "group");
+        assertServiceKey(port, serviceName, "0_0_0", "group");
+        assertServiceKey(port, serviceName, "0.0.0", "group");
+        assertServiceKey(port, serviceName, "", "group");
+        assertServiceKey(port, serviceName, null, "group");
+
+        assertServiceKey(port, serviceName, "", "");
+        assertServiceKey(port, serviceName, "", null);
+        assertServiceKey(port, serviceName, null, "");
+        assertServiceKey(port, serviceName, null, null);
+
+        assertServiceKey(port, serviceName, "", " ");
+        assertServiceKey(port, serviceName, " ", "");
+        assertServiceKey(port, serviceName, " ", " ");
+    }
+
+    private void assertServiceKey(int port, String serviceName, String serviceVersion, String serviceGroup) {
+        Assertions.assertEquals(
+                serviceKeyOldImpl(port, serviceName, serviceVersion, serviceGroup),
+                ProtocolUtils.serviceKey(port, serviceName, serviceVersion, serviceGroup)
+        );
+    }
+
+    /**
+     * 来自 ProtocolUtils.serviceKey(int, String, String, String) 老版本的实现,用于对比测试!
+     */
+    private static String serviceKeyOldImpl(int port, String serviceName, String serviceVersion, String serviceGroup) {
+        StringBuilder buf = new StringBuilder();
+        if (serviceGroup != null && serviceGroup.length() > 0) {
+            buf.append(serviceGroup);
+            buf.append("/");
+        }
+        buf.append(serviceName);
+        if (serviceVersion != null && serviceVersion.length() > 0 && !"0.0.0".equals(serviceVersion)) {
+            buf.append(":");
+            buf.append(serviceVersion);
+        }
+        buf.append(":");
+        buf.append(port);
+        return buf.toString();
+    }
+
+}