From 76b84365234ce53cd6b2509947beed9ad2c28d4e Mon Sep 17 00:00:00 2001 From: Jon Marius Venstad Date: Fri, 8 Jan 2021 22:30:14 +0100 Subject: Cache CompoundName and Binding instances created during compilation --- .../profile/AllValuesQueryProfileVisitor.java | 6 +++--- .../search/query/profile/DimensionBinding.java | 3 ++- .../query/profile/PrefixQueryProfileVisitor.java | 22 +++++++++++++++------- .../yahoo/search/query/profile/QueryProfile.java | 10 ++++++---- .../search/query/profile/QueryProfileCompiler.java | 14 +++++++------- 5 files changed, 33 insertions(+), 22 deletions(-) (limited to 'container-search/src') diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/AllValuesQueryProfileVisitor.java b/container-search/src/main/java/com/yahoo/search/query/profile/AllValuesQueryProfileVisitor.java index 68bf112133a..40e22e8bcb5 100644 --- a/container-search/src/main/java/com/yahoo/search/query/profile/AllValuesQueryProfileVisitor.java +++ b/container-search/src/main/java/com/yahoo/search/query/profile/AllValuesQueryProfileVisitor.java @@ -16,8 +16,8 @@ final class AllValuesQueryProfileVisitor extends PrefixQueryProfileVisitor { private final Map values = new HashMap<>(); /* Lists all values starting at prefix */ - public AllValuesQueryProfileVisitor(CompoundName prefix) { - super(prefix); + public AllValuesQueryProfileVisitor(CompoundName prefix, Map> pathCache) { + super(prefix, pathCache); } @Override @@ -43,7 +43,7 @@ final class AllValuesQueryProfileVisitor extends PrefixQueryProfileVisitor { QueryProfile owner, DimensionValues variant, DimensionBinding binding) { - CompoundName fullName = currentPrefix.append(key); + CompoundName fullName = cache.computeIfAbsent(currentPrefix, __ -> new HashMap<>()).computeIfAbsent(key, currentPrefix::append); ValueWithSource existing = values.get(fullName.toString()); diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/DimensionBinding.java b/container-search/src/main/java/com/yahoo/search/query/profile/DimensionBinding.java index c6f3d923817..43462e8f327 100644 --- a/container-search/src/main/java/com/yahoo/search/query/profile/DimensionBinding.java +++ b/container-search/src/main/java/com/yahoo/search/query/profile/DimensionBinding.java @@ -4,6 +4,7 @@ package com.yahoo.search.query.profile; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; /** * An immutable, binding of a list of dimensions to dimension values @@ -203,7 +204,7 @@ public class DimensionBinding { @Override public int hashCode() { - return dimensions.hashCode() + 17 * values.hashCode(); + return Objects.hash(dimensions, values); } } diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/PrefixQueryProfileVisitor.java b/container-search/src/main/java/com/yahoo/search/query/profile/PrefixQueryProfileVisitor.java index 690a48f8124..c6c2eba0ea7 100644 --- a/container-search/src/main/java/com/yahoo/search/query/profile/PrefixQueryProfileVisitor.java +++ b/container-search/src/main/java/com/yahoo/search/query/profile/PrefixQueryProfileVisitor.java @@ -3,6 +3,11 @@ package com.yahoo.search.query.profile; import com.yahoo.processing.request.CompoundName; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + /** * A query profile visitor which keeps track of name prefixes and can skip values outside a given prefix * @@ -10,18 +15,22 @@ import com.yahoo.processing.request.CompoundName; */ abstract class PrefixQueryProfileVisitor extends QueryProfileVisitor { + protected final Map> cache; + /** Only call onValue/onQueryProfile for nodes having this prefix */ private final CompoundName prefix; /** The current prefix, relative to prefix. */ protected CompoundName currentPrefix = CompoundName.empty; + private final Deque currentPrefixes = new ArrayDeque<>(); private int prefixComponentIndex = -1; - public PrefixQueryProfileVisitor(CompoundName prefix) { + public PrefixQueryProfileVisitor(CompoundName prefix, Map> cache) { if (prefix == null) prefix = CompoundName.empty; this.prefix = prefix; + this.cache = cache; } @Override @@ -40,18 +49,17 @@ abstract class PrefixQueryProfileVisitor extends QueryProfileVisitor { @Override public final boolean enter(String name) { - prefixComponentIndex++; - if (prefixComponentIndex-1 < prefix.size()) return true; // we're in the given prefix, which should not be included in the name - currentPrefix = currentPrefix.append(name); + if (prefixComponentIndex++ < prefix.size()) return true; // we're in the given prefix, which should not be included in the name + currentPrefixes.push(currentPrefix); + currentPrefix = cache.computeIfAbsent(currentPrefix, __ -> new HashMap<>()).computeIfAbsent(name, currentPrefix::append); return true; } @Override public final void leave(String name) { - prefixComponentIndex--; - if (prefixComponentIndex < prefix.size()) return; // we're in the given prefix, which should not be included in the name + if (--prefixComponentIndex < prefix.size()) return; // we're in the given prefix, which should not be included in the name if ( ! name.isEmpty() && ! currentPrefix.isEmpty()) - currentPrefix = currentPrefix.first(currentPrefix.size() - 1); + currentPrefix = currentPrefixes.pop(); } /** diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfile.java b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfile.java index be4a683d9d2..1978740014c 100644 --- a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfile.java +++ b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfile.java @@ -18,7 +18,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -266,10 +265,13 @@ public class QueryProfile extends FreezableSimpleComponent implements Cloneable } AllValuesQueryProfileVisitor visitValues(CompoundName prefix, Map context) { - DimensionBinding dimensionBinding = DimensionBinding.createFrom(getDimensions(), context); + return visitValues(prefix, context, new HashMap<>()); + } - AllValuesQueryProfileVisitor visitor = new AllValuesQueryProfileVisitor(prefix); - accept(visitor, dimensionBinding, null); + AllValuesQueryProfileVisitor visitValues(CompoundName prefix, Map context, + Map> pathCache) { + AllValuesQueryProfileVisitor visitor = new AllValuesQueryProfileVisitor(prefix, pathCache); + accept(visitor, DimensionBinding.createFrom(getDimensions(), context), null); return visitor; } diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java index b3fbc1525e6..24426b379e9 100644 --- a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java +++ b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java @@ -50,13 +50,13 @@ public class QueryProfileCompiler { log.fine(() -> "Compiling " + in + " having " + variants.size() + " variants"); Map> pathCache = new HashMap<>(); - for (DimensionBindingForPath variant : variants) { - log.finer(() -> " Compiling variant " + variant); - // TODO jonmv: consider visiting with sets of bindings for each path - for (Map.Entry entry : in.visitValues(variant.path(), variant.binding().getContext()).valuesWithSource().entrySet()) { - CompoundName fullName = pathCache.computeIfAbsent(variant.path, path -> new HashMap<>()) - .computeIfAbsent(entry.getKey(), variant.path::append); - Binding variantBinding = Binding.createFrom(variant.binding()); + Map bindingCache = new HashMap<>(); + for (var variant : variants) { + log.finer(() -> "Compiling variant " + variant); + Binding variantBinding = bindingCache.computeIfAbsent(variant.binding(), Binding::createFrom); + for (var entry : in.visitValues(variant.path(), variant.binding().getContext(), pathCache).valuesWithSource().entrySet()) { + CompoundName fullName = pathCache.computeIfAbsent(variant.path(), __ -> new HashMap<>()) + .computeIfAbsent(entry.getKey(), variant.path()::append); values.put(fullName, variantBinding, entry.getValue()); if (entry.getValue().isUnoverridable()) unoverridables.put(fullName, variantBinding, Boolean.TRUE); -- cgit v1.2.3