diff --git a/reactor-netty-core/src/main/java/reactor/netty/internal/util/MapUtils.java b/reactor-netty-core/src/main/java/reactor/netty/internal/util/MapUtils.java
index 1e3e8aaa08..ad20dc3bad 100644
--- a/reactor-netty-core/src/main/java/reactor/netty/internal/util/MapUtils.java
+++ b/reactor-netty-core/src/main/java/reactor/netty/internal/util/MapUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 VMware, Inc. or its affiliates, All Rights Reserved.
+ * Copyright (c) 2022-2023 VMware, Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,8 +19,7 @@
import java.util.function.Function;
/**
- * It's a temporary workaround for Java 8 specific performance issue JDK-8161372
- * and this class should be removed once the Java 8 support is dropped.
+ * This class contains temporary workarounds for Java 8 {@link Map} issues.
*
Note: This utility class is for internal use only. It can be removed at any time.
*
* @author zimatars
@@ -29,6 +28,24 @@
public final class MapUtils {
/**
+ * This is a temporary workaround for Java 8 issue https://bugs.openjdk.org/browse/JDK-8186958. Fix is available
+ * in Java 19.
+ *
+ * Calculate the initial capacity for the {@link Map} from the expected size and the default load factor
+ * for the {@link Map} (0.75).
+ *
+ * @param expectedSize the expected size
+ * @return the initial capacity for the {@link Map}
+ * @since 1.0.31
+ */
+ public static int calculateInitialCapacity(int expectedSize) {
+ return (int) Math.ceil(expectedSize / 0.75);
+ }
+
+ /**
+ * This is a temporary workaround for Java 8 specific performance issue https://bugs.openjdk.org/browse/JDK-8161372.
+ * Fix is available in Java 9.
+ *
* ConcurrentHashMap.computeIfAbsent(k,v) locks when k is present.
* Add pre-screen before locking inside computeIfAbsent.
*
Note: This utility is not for a general purpose usage.
diff --git a/reactor-netty-core/src/main/java/reactor/netty/tcp/TcpServerBind.java b/reactor-netty-core/src/main/java/reactor/netty/tcp/TcpServerBind.java
index 202febad93..87d93ecb00 100644
--- a/reactor-netty-core/src/main/java/reactor/netty/tcp/TcpServerBind.java
+++ b/reactor-netty-core/src/main/java/reactor/netty/tcp/TcpServerBind.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 VMware, Inc. or its affiliates, All Rights Reserved.
+ * Copyright (c) 2017-2023 VMware, Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
import io.netty.channel.ChannelOption;
import reactor.core.publisher.Mono;
import reactor.netty.DisposableServer;
+import reactor.netty.internal.util.MapUtils;
import java.net.InetSocketAddress;
import java.util.Collections;
@@ -37,7 +38,7 @@ final class TcpServerBind extends TcpServer {
final TcpServerConfig config;
TcpServerBind() {
- Map, Boolean> childOptions = new HashMap<>(2);
+ Map, Boolean> childOptions = new HashMap<>(MapUtils.calculateInitialCapacity(2));
childOptions.put(ChannelOption.AUTO_READ, false);
childOptions.put(ChannelOption.TCP_NODELAY, true);
this.config = new TcpServerConfig(
diff --git a/reactor-netty-core/src/main/java/reactor/netty/transport/ServerTransport.java b/reactor-netty-core/src/main/java/reactor/netty/transport/ServerTransport.java
index 873851afff..70f2147b0c 100644
--- a/reactor-netty-core/src/main/java/reactor/netty/transport/ServerTransport.java
+++ b/reactor-netty-core/src/main/java/reactor/netty/transport/ServerTransport.java
@@ -537,7 +537,7 @@ public void disposeNow(Duration timeout) {
Mono terminateSignals = Mono.empty();
if (config.channelGroup != null && config.channelGroup.size() > 0) {
HashMap>> channelsToMono =
- new HashMap<>((int) Math.ceil(config.channelGroup.size() / 0.75));
+ new HashMap<>(MapUtils.calculateInitialCapacity(config.channelGroup.size()));
// Wait for the running requests to finish
for (Channel channel : config.channelGroup) {
Channel parent = channel.parent();
diff --git a/reactor-netty-core/src/main/java/reactor/netty/transport/TransportConfig.java b/reactor-netty-core/src/main/java/reactor/netty/transport/TransportConfig.java
index be335407eb..5a77bf4b88 100644
--- a/reactor-netty-core/src/main/java/reactor/netty/transport/TransportConfig.java
+++ b/reactor-netty-core/src/main/java/reactor/netty/transport/TransportConfig.java
@@ -39,6 +39,7 @@
import reactor.netty.NettyPipeline;
import reactor.netty.channel.ChannelMetricsRecorder;
import reactor.netty.channel.ChannelOperations;
+import reactor.netty.internal.util.MapUtils;
import reactor.netty.resources.LoopResources;
import reactor.util.Logger;
import reactor.util.Loggers;
@@ -351,7 +352,7 @@ protected static Map updateMap(Map parentMap, Object key, @Nu
return value == null ? parentMap : Collections.singletonMap((K) key, (V) value);
}
else {
- Map attrs = new HashMap<>(parentMap.size() + 1);
+ Map attrs = new HashMap<>(MapUtils.calculateInitialCapacity(parentMap.size() + 1));
attrs.putAll(parentMap);
if (value == null) {
attrs.remove(key);
diff --git a/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpPredicate.java b/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpPredicate.java
index 42812fef5b..58b7deba15 100644
--- a/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpPredicate.java
+++ b/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2021 VMware, Inc. or its affiliates, All Rights Reserved.
+ * Copyright (c) 2011-2023 VMware, Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpVersion;
+import reactor.netty.internal.util.MapUtils;
import reactor.util.annotation.Nullable;
import static java.util.Objects.requireNonNull;
@@ -344,7 +345,7 @@ public boolean matches(String uri) {
* @return the path parameters from the uri. Never {@code null}.
*/
final Map match(String uri) {
- Map pathParameters = new HashMap<>(pathVariables.size());
+ Map pathParameters = new HashMap<>(MapUtils.calculateInitialCapacity(pathVariables.size()));
Matcher m = matcher(uri);
if (m.matches()) {
diff --git a/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerBind.java b/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerBind.java
index 3b90d1ed27..b055147544 100644
--- a/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerBind.java
+++ b/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerBind.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 VMware, Inc. or its affiliates, All Rights Reserved.
+ * Copyright (c) 2017-2023 VMware, Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
import io.netty.util.AttributeKey;
import reactor.core.publisher.Mono;
import reactor.netty.DisposableServer;
+import reactor.netty.internal.util.MapUtils;
import reactor.netty.tcp.SslProvider;
import reactor.netty.tcp.TcpServerConfig;
@@ -41,7 +42,7 @@ final class HttpServerBind extends HttpServer {
final HttpServerConfig config;
HttpServerBind() {
- Map, Boolean> childOptions = new HashMap<>(2);
+ Map, Boolean> childOptions = new HashMap<>(MapUtils.calculateInitialCapacity(2));
childOptions.put(ChannelOption.AUTO_READ, false);
childOptions.put(ChannelOption.TCP_NODELAY, true);
this.config = new HttpServerConfig(