#1798 - Optimization around constructing UriTemplate when supplying TemplateVariables of same type

Reduce the repeated merge routines on ExpandGroups.

Before:
Benchmark                          Mode  Cnt     Score     Error  Units
TemplateVariableBenchmark.concat  thrpt    3  3150,261 ± 263,525  ops/s

After:
Benchmark                          Mode  Cnt      Score      Error  Units
TemplateVariableBenchmark.concat  thrpt    3  55275,436 ± 3778,690  ops/s
This commit is contained in:
Michael.Rocke
2022-04-20 17:06:36 +01:00
committed by Oliver Drotbohm
parent 29c8d9b9c1
commit fd7dc6f6b1
3 changed files with 31 additions and 27 deletions

View File

@@ -21,7 +21,7 @@ import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.EnumSet;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -499,7 +499,7 @@ public final class TemplateVariable implements Serializable, UriTemplate.Expanda
*/
COMPOSITE_PARAM("*", "", true);
private static final List<VariableType> COMBINABLE_TYPES = Arrays.asList(REQUEST_PARAM, REQUEST_PARAM_CONTINUED);
private static final EnumSet<VariableType> COMBINABLE_TYPES = EnumSet.of(REQUEST_PARAM, REQUEST_PARAM_CONTINUED);
static final String DEFAULT_SEPARATOR = ",";
private final String key, combiner;

View File

@@ -68,11 +68,12 @@ public final class TemplateVariables implements Iterable<TemplateVariable>, Seri
for (TemplateVariable variable : variables) {
processed.add(variable.isRequestParameterVariable() && requestParameterFound
boolean isRequestParameter = variable.isRequestParameterVariable();
processed.add(isRequestParameter && requestParameterFound
? variable.withType(REQUEST_PARAM_CONTINUED)
: variable);
if (variable.isRequestParameterVariable()) {
if (isRequestParameter) {
requestParameterFound = true;
}
}
@@ -100,12 +101,11 @@ public final class TemplateVariables implements Iterable<TemplateVariable>, Seri
List<TemplateVariable> result = new ArrayList<>(this.variables.size() + variables.size());
result.addAll(this.variables);
List<TemplateVariable> filtered = variables.stream() //
.filter(variable -> !containsEquivalentFor(variable)).collect(Collectors.toList());
result.addAll(filtered);
for (TemplateVariable otherVariable : variables) {
if (!containsEquivalentFor(otherVariable)) {
result.add(otherVariable);
}
}
return new TemplateVariables(result);
}
@@ -133,9 +133,12 @@ public final class TemplateVariables implements Iterable<TemplateVariable>, Seri
}
private boolean containsEquivalentFor(TemplateVariable candidate) {
return this.variables.stream() //
.anyMatch(variable -> variable.isEquivalent(candidate));
for (TemplateVariable variable : variables) {
if (variable.isEquivalent(candidate)) {
return true;
}
}
return false;
}
/*

View File

@@ -18,13 +18,7 @@ package org.springframework.hateoas;
import java.io.Serializable;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -172,13 +166,10 @@ public class UriTemplate implements Iterable<TemplateVariable>, Serializable {
}
UriComponents components = UriComponentsBuilder.fromUriString(baseUri).build();
MultiValueMap<String, String> parameters = components.getQueryParams();
List<TemplateVariable> result = new ArrayList<>();
String newOriginal = template;
ExpandGroups groups = this.groups;
for (TemplateVariable variable : variables) {
MultiValueMap<String, String> parameters = components.getQueryParams();
boolean isRequestParam = variable.isRequestParameterVariable();
boolean alreadyPresent = parameters.containsKey(variable.getName());
@@ -195,9 +186,20 @@ public class UriTemplate implements Iterable<TemplateVariable>, Serializable {
variable = variable.withType(VariableType.REQUEST_PARAM_CONTINUED);
}
ExpandGroup existing = groups.findLastExpandGroupOfType(variable.getType());
ExpandGroup group = new ExpandGroup(Collections.singletonList(variable));
result.add(variable);
}
String newOriginal = template;
ExpandGroups groups = this.groups;
LinkedHashMap<VariableType, List<TemplateVariable>> groupedByVariableType = result.stream()
.collect(
Collectors.groupingBy(TemplateVariable::getType, LinkedHashMap::new, Collectors.toList()));
for (Map.Entry<VariableType, List<TemplateVariable>> entry : groupedByVariableType.entrySet()) {
ExpandGroup existing = groups.findLastExpandGroupOfType(entry.getKey());
ExpandGroup group = new ExpandGroup(entry.getValue());
if (existing != null) {
group = existing.merge(group);
newOriginal = newOriginal.replace(existing.asString(), group.asString());
@@ -206,7 +208,6 @@ public class UriTemplate implements Iterable<TemplateVariable>, Serializable {
}
groups = groups.addOrAugment(group);
result.add(variable);
}
return new UriTemplate(baseUri, newOriginal, this.variables.concat(result), groups);