You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by xi...@apache.org on 2023/02/09 03:48:13 UTC
[shenyu] branch master updated: Fixed jdk8 Map computeIfAbsent performance bug (#4338)
This is an automated email from the ASF dual-hosted git repository.
xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 0a136faf6 Fixed jdk8 Map computeIfAbsent performance bug (#4338)
0a136faf6 is described below
commit 0a136faf622e16778dd004d7d5db6c791feeb1b6
Author: caojiajun <zj...@163.com>
AuthorDate: Thu Feb 9 11:48:07 2023 +0800
Fixed jdk8 Map computeIfAbsent performance bug (#4338)
* Fixed jdk8 Map computeIfAbsent performance bug
* update code for checkstyle
---------
Co-authored-by: hzcaojiajun <hz...@corp.netease.com>
Co-authored-by: xiaoyu <xi...@apache.org>
---
.../admin/service/impl/UpstreamCheckService.java | 3 ++-
.../admin/validation/validator/ExistedValidator.java | 3 ++-
.../java/org/apache/shenyu/common/utils/MapUtils.java | 19 +++++++++++++++++++
.../loadbalancer/cache/UpstreamCacheManager.java | 3 ++-
.../shenyu/loadbalancer/cache/UpstreamCheckTask.java | 3 ++-
.../loadbalancer/spi/RoundRobinLoadBalancer.java | 5 +++--
.../plugin/base/cache/CommonPluginDataSubscriber.java | 3 ++-
.../shenyu/plugin/base/cache/MatchDataCache.java | 3 ++-
.../shenyu/plugin/grpc/cache/GrpcClientCache.java | 3 ++-
.../nacos/NacosClientServerRegisterRepository.java | 7 ++++---
.../consul/ConsulInstanceRegisterRepository.java | 3 ++-
.../sync/data/nacos/handler/NacosCacheHandler.java | 3 ++-
12 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java
index 4ecb0b5b5..55c91d155 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/UpstreamCheckService.java
@@ -47,6 +47,7 @@ import org.apache.shenyu.common.dto.convert.selector.ZombieUpstream;
import org.apache.shenyu.common.enums.ConfigGroupEnum;
import org.apache.shenyu.common.enums.DataEventTypeEnum;
import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.common.utils.UpstreamCheckUtils;
import org.apache.shenyu.register.common.config.ShenyuRegisterCenterConfig;
import org.slf4j.Logger;
@@ -184,7 +185,7 @@ public class UpstreamCheckService {
return false;
}
- List<CommonUpstream> upstreams = UPSTREAM_MAP.computeIfAbsent(selectorId, k -> new CopyOnWriteArrayList<>());
+ List<CommonUpstream> upstreams = MapUtils.computeIfAbsent(UPSTREAM_MAP, selectorId, k -> new CopyOnWriteArrayList<>());
if (commonUpstream.isStatus()) {
Optional<CommonUpstream> exists = upstreams.stream().filter(item -> StringUtils.isNotBlank(item.getUpstreamUrl())
&& item.getUpstreamUrl().equals(commonUpstream.getUpstreamUrl())).findFirst();
diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/validation/validator/ExistedValidator.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/validation/validator/ExistedValidator.java
index b741a25bc..36abfa7aa 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/validation/validator/ExistedValidator.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/validation/validator/ExistedValidator.java
@@ -21,6 +21,7 @@ import org.apache.shenyu.admin.spring.SpringBeanUtils;
import org.apache.shenyu.admin.utils.Assert;
import org.apache.shenyu.admin.validation.ExistProvider;
import org.apache.shenyu.admin.validation.annotation.Existed;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.common.utils.ReflectUtils;
import java.io.Serializable;
@@ -66,7 +67,7 @@ public class ExistedValidator implements ConstraintValidator<Existed, Serializab
}
private ExistProvider getExistProvider() {
- return providerCacheMap.computeIfAbsent(annotation.provider().getName(), key -> SpringBeanUtils.getInstance().getBean(annotation.provider()));
+ return MapUtils.computeIfAbsent(providerCacheMap, annotation.provider().getName(), key -> SpringBeanUtils.getInstance().getBean(annotation.provider()));
}
private Boolean doValid(final Serializable value) {
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/MapUtils.java b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/MapUtils.java
index b0801dd60..1c44c3f97 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/MapUtils.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/MapUtils.java
@@ -20,6 +20,7 @@ package org.apache.shenyu.common.utils;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.function.Function;
import java.util.stream.Collectors;
public class MapUtils {
@@ -35,4 +36,22 @@ public class MapUtils {
.map(m -> m.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> Objects.toString(e.getValue(), null))))
.orElse(null);
}
+
+ /**
+ * This is jdk8 performance bug, see: https://bugs.openjdk.java.net/browse/JDK-8161372.
+ *
+ * @param map source map
+ * @param key key
+ * @param mappingFunction mappingFunction
+ * @param <K> k
+ * @param <V> v
+ * @return v
+ */
+ public static <K, V> V computeIfAbsent(final Map<K, V> map, final K key, final Function<? super K, ? extends V> mappingFunction) {
+ V v = map.get(key);
+ if (v != null) {
+ return v;
+ }
+ return map.computeIfAbsent(key, mappingFunction);
+ }
}
diff --git a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCacheManager.java b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCacheManager.java
index 75854cf08..899ae24db 100644
--- a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCacheManager.java
+++ b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCacheManager.java
@@ -23,6 +23,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.shenyu.common.concurrent.ShenyuThreadFactory;
import org.apache.shenyu.common.config.ShenyuConfig;
import org.apache.shenyu.common.config.ShenyuConfig.UpstreamCheck;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.common.utils.Singleton;
import org.apache.shenyu.loadbalancer.entity.Upstream;
@@ -140,7 +141,7 @@ public final class UpstreamCacheManager {
public void submit(final String selectorId, final List<Upstream> upstreamList) {
List<Upstream> validUpstreamList = upstreamList.stream().filter(Upstream::isStatus).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(validUpstreamList)) {
- List<Upstream> existUpstream = UPSTREAM_MAP.computeIfAbsent(selectorId, k -> Lists.newArrayList());
+ List<Upstream> existUpstream = MapUtils.computeIfAbsent(UPSTREAM_MAP, selectorId, k -> Lists.newArrayList());
existUpstream.stream().filter(upstream -> !validUpstreamList.contains(upstream))
.forEach(upstream -> task.triggerRemoveOne(selectorId, upstream));
validUpstreamList.stream().filter(upstream -> !existUpstream.contains(upstream))
diff --git a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCheckTask.java b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCheckTask.java
index 856a5e6c1..46b9ddc76 100644
--- a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCheckTask.java
+++ b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCheckTask.java
@@ -22,6 +22,7 @@ import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shenyu.common.concurrent.ShenyuThreadFactory;
import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.common.utils.UpstreamCheckUtils;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.slf4j.Logger;
@@ -251,7 +252,7 @@ public final class UpstreamCheckTask implements Runnable {
private void putToMap(final Map<String, List<Upstream>> map, final String selectorId, final Upstream upstream) {
synchronized (lock) {
- List<Upstream> list = map.computeIfAbsent(selectorId, k -> Lists.newArrayList());
+ List<Upstream> list = MapUtils.computeIfAbsent(map, selectorId, k -> Lists.newArrayList());
if (!list.contains(upstream)) {
list.add(upstream);
}
diff --git a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalancer.java b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalancer.java
index d62160ab0..da3e62bec 100644
--- a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalancer.java
+++ b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalancer.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.spi.Join;
@@ -42,7 +43,7 @@ public class RoundRobinLoadBalancer extends AbstractLoadBalancer {
@Override
public Upstream doSelect(final List<Upstream> upstreamList, final String ip) {
String key = upstreamList.get(0).getUrl();
- ConcurrentMap<String, WeightedRoundRobin> map = methodWeightMap.computeIfAbsent(key, k -> new ConcurrentHashMap<>(16));
+ ConcurrentMap<String, WeightedRoundRobin> map = MapUtils.computeIfAbsent(methodWeightMap, key, k -> new ConcurrentHashMap<>(16));
int totalWeight = 0;
long maxCurrent = Long.MIN_VALUE;
long now = System.currentTimeMillis();
@@ -51,7 +52,7 @@ public class RoundRobinLoadBalancer extends AbstractLoadBalancer {
for (Upstream upstream : upstreamList) {
String rKey = upstream.getUrl();
int weight = getWeight(upstream);
- WeightedRoundRobin weightedRoundRobin = map.computeIfAbsent(rKey, k -> {
+ WeightedRoundRobin weightedRoundRobin = MapUtils.computeIfAbsent(map, rKey, k -> {
WeightedRoundRobin roundRobin = new WeightedRoundRobin();
roundRobin.setWeight(weight);
return roundRobin;
diff --git a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
index 04e0a0240..408a3c432 100644
--- a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
+++ b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
@@ -24,6 +24,7 @@ import org.apache.shenyu.common.dto.SelectorData;
import org.apache.shenyu.common.enums.DataEventTypeEnum;
import org.apache.shenyu.common.enums.PluginHandlerEventEnum;
import org.apache.shenyu.common.enums.RuleTrieEventEnum;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
import org.apache.shenyu.plugin.base.event.RuleTrieEvent;
import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
@@ -83,7 +84,7 @@ public class CommonPluginDataSubscriber implements PluginDataSubscriber {
}
for (PluginDataHandler handler : handlers) {
String pluginNamed = handler.pluginNamed();
- handlerMap.computeIfAbsent(pluginNamed, name -> {
+ MapUtils.computeIfAbsent(handlerMap, pluginNamed, name -> {
LOG.info("shenyu auto add extends plugin data handler name is :{}", pluginNamed);
return handler;
});
diff --git a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MatchDataCache.java b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MatchDataCache.java
index 5b84b1e1a..e47a8709c 100644
--- a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MatchDataCache.java
+++ b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MatchDataCache.java
@@ -21,6 +21,7 @@ import com.google.common.collect.Maps;
import org.apache.shenyu.common.cache.MemorySafeWindowTinyLFUMap;
import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.utils.MapUtils;
import java.util.Map;
import java.util.Optional;
@@ -81,7 +82,7 @@ public final class MatchDataCache {
* @param maxMemory the max memory
*/
public void cacheSelectorData(final String path, final SelectorData selectorData, final Integer maxMemory) {
- SELECTOR_DATA_MAP.computeIfAbsent(selectorData.getPluginName(), map -> new MemorySafeWindowTinyLFUMap<>(maxMemory, 1 << 16)).put(path, selectorData);
+ MapUtils.computeIfAbsent(SELECTOR_DATA_MAP, selectorData.getPluginName(), map -> new MemorySafeWindowTinyLFUMap<>(maxMemory, 1 << 16)).put(path, selectorData);
}
/**
diff --git a/shenyu-plugin/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/GrpcClientCache.java b/shenyu-plugin/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/GrpcClientCache.java
index 7b9a1ba66..abc493993 100644
--- a/shenyu-plugin/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/GrpcClientCache.java
+++ b/shenyu-plugin/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/GrpcClientCache.java
@@ -18,6 +18,7 @@
package org.apache.shenyu.plugin.grpc.cache;
import com.google.common.collect.Maps;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.plugin.grpc.client.GrpcClientBuilder;
import org.apache.shenyu.plugin.grpc.client.ShenyuGrpcClient;
@@ -50,7 +51,7 @@ public final class GrpcClientCache {
* @param contextPath contextPath
*/
public static void initGrpcClient(final String contextPath) {
- CLIENT_CACHE.computeIfAbsent(contextPath, s -> GrpcClientBuilder.buildClient(contextPath));
+ MapUtils.computeIfAbsent(CLIENT_CACHE, contextPath, s -> GrpcClientBuilder.buildClient(contextPath));
}
/**
diff --git a/shenyu-register-center/shenyu-register-client-server/shenyu-register-client-server-nacos/src/main/java/org/apache/shenyu/register/client/server/nacos/NacosClientServerRegisterRepository.java b/shenyu-register-center/shenyu-register-client-server/shenyu-register-client-server-nacos/src/main/java/org/apache/shenyu/register/client/server/nacos/NacosClientServerRegisterRepository.java
index d62283fef..242f55036 100644
--- a/shenyu-register-center/shenyu-register-client-server/shenyu-register-client-server-nacos/src/main/java/org/apache/shenyu/register/client/server/nacos/NacosClientServerRegisterRepository.java
+++ b/shenyu-register-center/shenyu-register-client-server/shenyu-register-client-server-nacos/src/main/java/org/apache/shenyu/register/client/server/nacos/NacosClientServerRegisterRepository.java
@@ -33,6 +33,7 @@ import org.apache.shenyu.common.constant.NacosPathConstants;
import org.apache.shenyu.common.enums.RpcTypeEnum;
import org.apache.shenyu.common.exception.ShenyuException;
import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.register.common.config.ShenyuRegisterCenterConfig;
import org.apache.shenyu.register.common.dto.MetaDataRegisterDTO;
import org.apache.shenyu.register.common.dto.URIRegisterDTO;
@@ -125,8 +126,8 @@ public class NacosClientServerRegisterRepository implements ShenyuClientServerRe
metadataConfigCache.add(serviceConfigName);
String metadata = healthyInstance.getMetadata().get("uriMetadata");
URIRegisterDTO uriRegisterDTO = GsonUtils.getInstance().fromJson(metadata, URIRegisterDTO.class);
- services.computeIfAbsent(contextPath, k -> new ArrayList<>()).add(uriRegisterDTO);
- uriServiceCache.computeIfAbsent(serviceName, k -> new ConcurrentSkipListSet<>()).add(contextPath);
+ MapUtils.computeIfAbsent(services, contextPath, k -> new ArrayList<>()).add(uriRegisterDTO);
+ MapUtils.computeIfAbsent(uriServiceCache, serviceName, k -> new ConcurrentSkipListSet<>()).add(contextPath);
});
if (RPC_URI_TYPE_SET.contains(rpcType)) {
services.values().forEach(this::publishRegisterURI);
@@ -137,7 +138,7 @@ public class NacosClientServerRegisterRepository implements ShenyuClientServerRe
List<Instance> instances = ((NamingEvent) event).getInstances();
instances.forEach(instance -> {
String contextPath = instance.getMetadata().get("contextPath");
- uriServiceCache.computeIfAbsent(serviceName, k -> new ConcurrentSkipListSet<>()).add(contextPath);
+ MapUtils.computeIfAbsent(uriServiceCache, serviceName, k -> new ConcurrentSkipListSet<>()).add(contextPath);
});
refreshURIService(rpcType, serviceName);
}
diff --git a/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-consul/src/main/java/org/apache/shenyu/register/instance/consul/ConsulInstanceRegisterRepository.java b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-consul/src/main/java/org/apache/shenyu/register/instance/consul/ConsulInstanceRegisterRepository.java
index a45ef4749..56b0539cd 100644
--- a/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-consul/src/main/java/org/apache/shenyu/register/instance/consul/ConsulInstanceRegisterRepository.java
+++ b/shenyu-register-center/shenyu-register-instance/shenyu-register-instance-consul/src/main/java/org/apache/shenyu/register/instance/consul/ConsulInstanceRegisterRepository.java
@@ -29,6 +29,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.common.concurrent.ShenyuThreadFactory;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.register.instance.api.ShenyuInstanceRegisterRepository;
import org.apache.shenyu.register.instance.api.config.RegisterConfig;
import org.apache.shenyu.register.instance.api.entity.InstanceEntity;
@@ -168,7 +169,7 @@ public class ConsulInstanceRegisterRepository implements ShenyuInstanceRegisterR
return;
}
synchronized (lock) {
- eventListeners = listenerMap.computeIfAbsent(selectKey, s -> new HashSet<>());
+ eventListeners = MapUtils.computeIfAbsent(listenerMap, selectKey, s -> new HashSet<>());
}
eventListeners.add(watcherListener);
watchFutures.add(this.executor.scheduleWithFixedDelay(() -> this.watchConfigKeyValues(selectKey),
diff --git a/shenyu-sync-data-center/shenyu-sync-data-nacos/src/main/java/org/apache/shenyu/sync/data/nacos/handler/NacosCacheHandler.java b/shenyu-sync-data-center/shenyu-sync-data-nacos/src/main/java/org/apache/shenyu/sync/data/nacos/handler/NacosCacheHandler.java
index e924ce94d..87e3f6462 100644
--- a/shenyu-sync-data-center/shenyu-sync-data-nacos/src/main/java/org/apache/shenyu/sync/data/nacos/handler/NacosCacheHandler.java
+++ b/shenyu-sync-data-center/shenyu-sync-data-nacos/src/main/java/org/apache/shenyu/sync/data/nacos/handler/NacosCacheHandler.java
@@ -29,6 +29,7 @@ import org.apache.shenyu.common.dto.PluginData;
import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.sync.data.api.AuthDataSubscriber;
import org.apache.shenyu.sync.data.api.MetaDataSubscriber;
import org.apache.shenyu.sync.data.api.PluginDataSubscriber;
@@ -171,7 +172,7 @@ public class NacosCacheHandler {
}
};
oc.change(getConfigAndSignListener(dataId, listener));
- LISTENERS.computeIfAbsent(dataId, key -> new ArrayList<>()).add(listener);
+ MapUtils.computeIfAbsent(LISTENERS, dataId, key -> new ArrayList<>()).add(listener);
}
protected interface OnChange {