diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml
index 1a68615a..b4a57709 100644
--- a/spring-cloud-gateway-server/pom.xml
+++ b/spring-cloud-gateway-server/pom.xml
@@ -223,6 +223,18 @@
junit-jupiter
test
+
+ org.openjdk.jmh
+ jmh-core
+ 1.20
+ test
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ 1.20
+ test
+
diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactory.java
index e9772fc3..f4a1d7c7 100644
--- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactory.java
+++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicateFactory.java
@@ -34,6 +34,7 @@ import org.springframework.web.util.pattern.PathPatternParser;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_PREDICATE_MATCHED_PATH_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_PREDICATE_MATCHED_PATH_ROUTE_ID_ATTR;
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_PREDICATE_PATH_CONTAINER_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.putUriTemplateVariables;
import static org.springframework.http.server.PathContainer.parsePath;
@@ -89,7 +90,9 @@ public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory parsePath(exchange.getRequest().getURI().getRawPath()));
PathPattern match = null;
for (int i = 0; i < pathPatterns.size(); i++) {
diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
index 6094c933..dfcc8036 100644
--- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
+++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
@@ -127,6 +127,11 @@ public final class ServerWebExchangeUtils {
public static final String GATEWAY_PREDICATE_MATCHED_PATH_ROUTE_ID_ATTR = qualify(
"gatewayPredicateMatchedPathRouteIdAttr");
+ /**
+ * Gateway predicate path container attribute name.
+ */
+ public static final String GATEWAY_PREDICATE_PATH_CONTAINER_ATTR = qualify("gatewayPredicatePathContainer");
+
/**
* Weight attribute name.
*/
diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicatePathContainerAttrBenchMarkTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicatePathContainerAttrBenchMarkTests.java
new file mode 100644
index 00000000..92032d0e
--- /dev/null
+++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/predicate/PathRoutePredicatePathContainerAttrBenchMarkTests.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013-2020 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.gateway.handler.predicate;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.util.function.Predicate;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.server.MockServerWebExchange;
+import org.springframework.web.server.ServerWebExchange;
+
+public class PathRoutePredicatePathContainerAttrBenchMarkTests {
+
+ private static List> predicates;
+
+ private static String PATH_PATTERN_PREFIX;
+
+ private final static String HOST = "http://localhost:8080";
+
+ private final static int ROUTES_NUM = 2000;
+
+ static {
+ predicates = new LinkedList<>();
+ PATH_PATTERN_PREFIX = String.format("/%s/%s/", RandomStringUtils.random(20, true, false),
+ RandomStringUtils.random(10, true, false));
+ for (int i = 0; i < ROUTES_NUM; i++) {
+ PathRoutePredicateFactory.Config config = new PathRoutePredicateFactory.Config()
+ .setPatterns(Collections.singletonList(PATH_PATTERN_PREFIX + i)).setMatchTrailingSlash(true);
+ Predicate predicate = new PathRoutePredicateFactory().apply(config);
+ predicates.add(predicate);
+ }
+ }
+
+ @Benchmark
+ @Threads(2)
+ @Fork(2)
+ @BenchmarkMode(Mode.All)
+ @Warmup(iterations = 1, time = 3)
+ @Measurement(iterations = 10, time = 1)
+ public void testPathContainerAttr() {
+ Random random = new Random();
+ MockServerHttpRequest request = MockServerHttpRequest
+ .get(HOST + PATH_PATTERN_PREFIX + random.nextInt(ROUTES_NUM)).build();
+ MockServerWebExchange exchange = MockServerWebExchange.from(request);
+ for (Predicate predicate : predicates) {
+ if (predicate.test(exchange)) {
+ break;
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ org.openjdk.jmh.Main.main(args);
+ }
+
+}