Skip to content

Commit

Permalink
More performance optimizations (#9070)
Browse files Browse the repository at this point in the history
Optimises route location and execution

---------

Co-authored-by: Jonas Konrad <[email protected]>
  • Loading branch information
dstepanov and yawkat authored Apr 5, 2023
1 parent 35fca05 commit d7819be
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public NettyWebSocketClientHandler(
this.genericWebSocketBean = webSocketBean;
String clientPath = webSocketBean.getBeanDefinition().stringValue(ClientWebSocket.class).orElse("");
UriMatchTemplate matchTemplate = UriMatchTemplate.of(clientPath);
this.matchInfo = matchTemplate.match(request.getPath()).orElse(null);
this.matchInfo = matchTemplate.tryMatch(request.getPath());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public Class<T> getDeclaringType() {
public String getMethodName() {
return method.getMethodName();
}

@Override
@NonNull
public AnnotationMetadata getAnnotationMetadata() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ protected final ExecutionFlow<MutableHttpResponse<?>> normalFlow() {

return runWithFilters(() ->
fulfillArguments(routeMatch)
.flatMap(rm -> routeExecutor.callRoute(context, rm, request))
.flatMap(this::handleStatusException)
.flatMap(rm -> routeExecutor.callRoute(context, rm, request).flatMap(res -> handleStatusException(res, rm)))
.onErrorResume(this::onErrorNoFilter));
}

Expand Down Expand Up @@ -181,8 +180,7 @@ final ExecutionFlow<MutableHttpResponse<?>> onErrorNoFilter(Throwable t) {
}
try {
return ExecutionFlow.just(errorRoute)
.flatMap(routeMatch -> routeExecutor.callRoute(context, routeMatch, request))
.flatMap(this::handleStatusException)
.flatMap(routeMatch -> routeExecutor.callRoute(context, routeMatch, request).flatMap(res -> handleStatusException(res, routeMatch)))
.onErrorResume(u -> createDefaultErrorResponseFlow(request, u))
.<MutableHttpResponse<?>>map(response -> {
response.setAttribute(HttpAttributes.EXCEPTION, cause);
Expand Down Expand Up @@ -266,7 +264,8 @@ protected final ExecutionFlow<MutableHttpResponse<?>> runWithFilters(Supplier<Ex
@Override
protected ExecutionFlow<? extends HttpResponse<?>> processResponse(HttpRequest<?> request, HttpResponse<?> response) {
RequestLifecycle.this.request = request;
return handleStatusException((MutableHttpResponse<?>) response)
RouteInfo<?> routeInfo = response.getAttribute(HttpAttributes.ROUTE_INFO, RouteInfo.class).orElse(null);
return handleStatusException((MutableHttpResponse<?>) response, routeInfo)
.onErrorResume(throwable -> onErrorNoFilter(throwable));
}

Expand All @@ -279,14 +278,17 @@ protected ExecutionFlow<? extends HttpResponse<?>> processFailure(HttpRequest<?>
return filterRunner.run(request);
}

private ExecutionFlow<MutableHttpResponse<?>> handleStatusException(MutableHttpResponse<?> response) {
RouteInfo<?> routeInfo = response.getAttribute(HttpAttributes.ROUTE_INFO, RouteInfo.class).orElse(null);
private ExecutionFlow<MutableHttpResponse<?>> handleStatusException(MutableHttpResponse<?> response, RouteMatch<?> routeMatch) {
RouteInfo<?> routeInfo = routeMatch == null ? null : routeMatch.getRouteInfo();
return handleStatusException(response, routeInfo);
}

private ExecutionFlow<MutableHttpResponse<?>> handleStatusException(MutableHttpResponse<?> response, RouteInfo<?> routeInfo) {
if (response.code() >= 400 && routeInfo != null && !routeInfo.isErrorRoute()) {
RouteMatch<Object> statusRoute = routeExecutor.findStatusRoute(request, response.status(), routeInfo);
if (statusRoute != null) {
return fulfillArguments(statusRoute)
.flatMap(routeMatch -> routeExecutor.callRoute(Context.empty(), routeMatch, request))
.flatMap(this::handleStatusException)
.flatMap(rm -> routeExecutor.callRoute(Context.empty(), rm, request).flatMap(res -> handleStatusException(res, rm)))
.onErrorResume(this::onErrorNoFilter);
}
}
Expand Down Expand Up @@ -369,8 +371,7 @@ protected final ExecutionFlow<MutableHttpResponse<?>> onStatusError(MutableHttpR
Optional<RouteMatch<Object>> statusRoute = routeExecutor.router.findStatusRoute(defaultResponse.status(), request);
if (statusRoute.isPresent()) {
return runWithFilters(() -> fulfillArguments(statusRoute.get())
.flatMap(routeMatch -> routeExecutor.callRoute(context, routeMatch, request))
.flatMap(this::handleStatusException)
.flatMap(routeMatch -> routeExecutor.callRoute(context, routeMatch, request).flatMap(res -> handleStatusException(res, routeMatch)))
.onErrorResume(this::onErrorNoFilter));
}
if (request.getMethod() != HttpMethod.HEAD) {
Expand Down
37 changes: 23 additions & 14 deletions http/src/main/java/io/micronaut/http/uri/UriMatchTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package io.micronaut.http.uri;

import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.util.ObjectUtils;

import java.util.ArrayList;
Expand Down Expand Up @@ -45,8 +47,8 @@ public class UriMatchTemplate extends UriTemplate implements UriMatcher {
private final boolean exactMatch;

// Matches cache
private Optional<UriMatchInfo> rootMatchInfo;
private Optional<UriMatchInfo> exactMatchInfo;
private UriMatchInfo rootMatchInfo;
private UriMatchInfo exactMatchInfo;

/**
* Construct a new URI template for the given template.
Expand Down Expand Up @@ -135,10 +137,7 @@ public String toPathString() {
final Optional<UriMatchVariable> umv = variables.stream()
.filter(v -> v.getName().equals(var.get())).findFirst();
if (umv.isPresent()) {
final UriMatchVariable uriMatchVariable = umv.get();
if (uriMatchVariable.isQuery()) {
return false;
}
return !umv.get().isQuery();
}
}
return true;
Expand All @@ -149,11 +148,21 @@ public String toPathString() {
* Match the given URI string.
*
* @param uri The uRI
* @return True if it matches
* @return an optional match
*/
@Override
@SuppressWarnings("java:S2789") // performance optimization
public Optional<UriMatchInfo> match(String uri) {
return Optional.ofNullable(tryMatch(uri));
}

/**
* Match the given URI string.
*
* @param uri The uRI
* @return a match or null
*/
@Nullable
public UriMatchInfo tryMatch(@NonNull String uri) {
if (uri == null) {
throw new IllegalArgumentException("Argument 'uri' cannot be null");
}
Expand All @@ -164,7 +173,7 @@ public Optional<UriMatchInfo> match(String uri) {

if (isRoot && (length == 0 || (length == 1 && uri.charAt(0) == '/'))) {
if (rootMatchInfo == null) {
rootMatchInfo = Optional.of(new DefaultUriMatchInfo(uri, Collections.emptyMap(), variables));
rootMatchInfo = new DefaultUriMatchInfo(uri, Collections.emptyMap(), variables);
}
return rootMatchInfo;
}
Expand All @@ -179,16 +188,16 @@ public Optional<UriMatchInfo> match(String uri) {
if (exactMatch) {
if (uri.equals(templateString)) {
if (exactMatchInfo == null) {
exactMatchInfo = Optional.of(new DefaultUriMatchInfo(uri, Collections.emptyMap(), variables));
exactMatchInfo = new DefaultUriMatchInfo(uri, Collections.emptyMap(), variables);
}
return exactMatchInfo;
}
return Optional.empty();
return null;
}
Matcher matcher = matchPattern.matcher(uri);
if (matcher.matches()) {
if (variables.isEmpty()) {
return Optional.of(new DefaultUriMatchInfo(uri, Collections.emptyMap(), variables));
return new DefaultUriMatchInfo(uri, Collections.emptyMap(), variables);
} else {
int count = matcher.groupCount();
Map<String, Object> variableMap = new LinkedHashMap<>(count);
Expand All @@ -201,10 +210,10 @@ public Optional<UriMatchInfo> match(String uri) {
String value = matcher.group(index);
variableMap.put(variable.getName(), value);
}
return Optional.of(new DefaultUriMatchInfo(uri, variableMap, variables));
return new DefaultUriMatchInfo(uri, variableMap, variables);
}
}
return Optional.empty();
return null;
}

@Override
Expand Down
7 changes: 6 additions & 1 deletion http/src/main/java/io/micronaut/http/uri/UriTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public class UriTemplate implements Comparable<UriTemplate> {
protected final String templateString;
final List<PathSegment> segments = new ArrayList<>();

private String asString;

/**
* Construct a new URI template for the given template.
*
Expand Down Expand Up @@ -247,7 +249,10 @@ public String expand(Object bean) {

@Override
public String toString() {
return toString(pathSegment -> true);
if (asString == null) {
asString = toString(pathSegment -> true);
}
return asString;
}

@Override
Expand Down
Loading

0 comments on commit d7819be

Please sign in to comment.