Make PathTrieIterator a Little more Memory Efficient (#44951) (#45070)

* There's no need to have the trie iterator hold another reference to the request object (which could be huge, see #44564)
* Also removed unused boolean field from trie node
This commit is contained in:
Armin Braun 2019-08-01 17:26:08 +02:00 committed by GitHub
parent 187f1e776b
commit 48dc53f8d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 11 additions and 12 deletions

View File

@ -57,7 +57,7 @@ public class PathTrie<T> {
WILDCARD_NODES_ALLOWED WILDCARD_NODES_ALLOWED
} }
static EnumSet<TrieMatchingMode> EXPLICIT_OR_ROOT_WILDCARD = private static final EnumSet<TrieMatchingMode> EXPLICIT_OR_ROOT_WILDCARD =
EnumSet.of(TrieMatchingMode.EXPLICIT_NODES_ONLY, TrieMatchingMode.WILDCARD_ROOT_NODES_ALLOWED); EnumSet.of(TrieMatchingMode.EXPLICIT_NODES_ONLY, TrieMatchingMode.WILDCARD_ROOT_NODES_ALLOWED);
public interface Decoder { public interface Decoder {
@ -79,17 +79,15 @@ public class PathTrie<T> {
public class TrieNode { public class TrieNode {
private transient String key; private transient String key;
private transient T value; private transient T value;
private boolean isWildcard;
private final String wildcard; private final String wildcard;
private transient String namedWildcard; private transient String namedWildcard;
private Map<String, TrieNode> children; private Map<String, TrieNode> children;
public TrieNode(String key, T value, String wildcard) { private TrieNode(String key, T value, String wildcard) {
this.key = key; this.key = key;
this.wildcard = wildcard; this.wildcard = wildcard;
this.isWildcard = (key.equals(wildcard));
this.value = value; this.value = value;
this.children = emptyMap(); this.children = emptyMap();
if (isNamedWildcard(key)) { if (isNamedWildcard(key)) {
@ -99,7 +97,7 @@ public class PathTrie<T> {
} }
} }
public void updateKeyWithNamedWildcard(String key) { private void updateKeyWithNamedWildcard(String key) {
this.key = key; this.key = key;
namedWildcard = key.substring(key.indexOf('{') + 1, key.indexOf('}')); namedWildcard = key.substring(key.indexOf('{') + 1, key.indexOf('}'));
} }
@ -110,7 +108,7 @@ public class PathTrie<T> {
children = unmodifiableMap(newChildren); children = unmodifiableMap(newChildren);
} }
public synchronized void insert(String[] path, int index, T value) { private synchronized void insert(String[] path, int index, T value) {
if (index >= path.length) if (index >= path.length)
return; return;
@ -145,7 +143,7 @@ public class PathTrie<T> {
node.insert(path, index + 1, value); node.insert(path, index + 1, value);
} }
public synchronized void insertOrUpdate(String[] path, int index, T value, BiFunction<T, T, T> updater) { private synchronized void insertOrUpdate(String[] path, int index, T value, BiFunction<T, T, T> updater) {
if (index >= path.length) if (index >= path.length)
return; return;
@ -357,14 +355,14 @@ public class PathTrie<T> {
return new PathTrieIterator<>(this, path, paramSupplier); return new PathTrieIterator<>(this, path, paramSupplier);
} }
class PathTrieIterator<T> implements Iterator<T> { private static class PathTrieIterator<T> implements Iterator<T> {
private final List<TrieMatchingMode> modes; private final List<TrieMatchingMode> modes;
private final Supplier<Map<String, String>> paramSupplier; private final Supplier<Map<String, String>> paramSupplier;
private final PathTrie<T> trie; private final PathTrie<T> trie;
private final String path; private final String path;
PathTrieIterator(PathTrie trie, String path, Supplier<Map<String, String>> paramSupplier) { PathTrieIterator(PathTrie<T> trie, String path, Supplier<Map<String, String>> paramSupplier) {
this.path = path; this.path = path;
this.trie = trie; this.trie = trie;
this.paramSupplier = paramSupplier; this.paramSupplier = paramSupplier;

View File

@ -363,11 +363,12 @@ public class RestController implements HttpServerTransport.Dispatcher {
// Between retrieving the correct path, we need to reset the parameters, // Between retrieving the correct path, we need to reset the parameters,
// otherwise parameters are parsed out of the URI that aren't actually handled. // otherwise parameters are parsed out of the URI that aren't actually handled.
final Map<String, String> originalParams = new HashMap<>(request.params()); final Map<String, String> originalParams = new HashMap<>(request.params());
final Map<String, String> requestParamsRef = request.params();
return handlers.retrieveAll(getPath(request), () -> { return handlers.retrieveAll(getPath(request), () -> {
// PathTrie modifies the request, so reset the params between each iteration // PathTrie modifies the request, so reset the params between each iteration
request.params().clear(); requestParamsRef.clear();
request.params().putAll(originalParams); requestParamsRef.putAll(originalParams);
return request.params(); return requestParamsRef;
}); });
} }