diff options
author | Lester Solbakken <lesters@oath.com> | 2020-04-26 09:53:12 +0200 |
---|---|---|
committer | Lester Solbakken <lesters@oath.com> | 2020-04-26 09:53:12 +0200 |
commit | 440dd0a324f2b889ec8190a59d89545fbc9937f6 (patch) | |
tree | adee14d2caa4ce88b319552fd498cc5b36935995 | |
parent | b2f1673a6d0f16368fe4528a7d1ff33eb6476506 (diff) |
Limit size of serialization context for functions without arguments
7 files changed, 61 insertions, 13 deletions
diff --git a/searchlib/abi-spec.json b/searchlib/abi-spec.json index d058104bf1b..6bce791914c 100644 --- a/searchlib/abi-spec.json +++ b/searchlib/abi-spec.json @@ -1416,7 +1416,8 @@ "public com.yahoo.searchlib.rankingexpression.ExpressionFunction getFunction(java.lang.String)", "protected com.google.common.collect.ImmutableMap functions()", "public java.lang.String getBinding(java.lang.String)", - "public com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withBindings(java.util.Map)" + "public com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withBindings(java.util.Map)", + "public com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withoutBindings()" ], "fields": [] }, @@ -1573,7 +1574,9 @@ "public void addArgumentTypeSerialization(java.lang.String, java.lang.String, com.yahoo.tensor.TensorType)", "public void addFunctionTypeSerialization(java.lang.String, com.yahoo.tensor.TensorType)", "public com.yahoo.searchlib.rankingexpression.rule.SerializationContext withBindings(java.util.Map)", + "public com.yahoo.searchlib.rankingexpression.rule.SerializationContext withoutBindings()", "public java.util.Map serializedFunctions()", + "public bridge synthetic com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withoutBindings()", "public bridge synthetic com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withBindings(java.util.Map)" ], "fields": [] diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java index 674571ff73e..559f690a32d 100755 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java @@ -134,7 +134,10 @@ public class ExpressionFunction { for (int i = 0; i < arguments.size() && i < argumentValues.size(); ++i) { argumentBindings.put(arguments.get(i), argumentValues.get(i).toString(new StringBuilder(), context, path, null).toString()); } - return new Instance(toSymbol(argumentBindings), body.getRoot().toString(new StringBuilder(), context.withBindings(argumentBindings), path, null).toString()); + context = argumentBindings.isEmpty() ? context.withoutBindings() : context.withBindings(argumentBindings); + String symbol = toSymbol(argumentBindings); + String expressionString = body.getRoot().toString(new StringBuilder(), context, path, null).toString(); + return new Instance(symbol, expressionString); } /** diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java index 83aabada8f0..6717bec0258 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java @@ -68,4 +68,9 @@ public class FunctionReferenceContext { return new FunctionReferenceContext(this.functions, bindings); } + /** Returns a fresh context without bindings */ + public FunctionReferenceContext withoutBindings() { + return new FunctionReferenceContext(this.functions); + } + } diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java index 8fec3603f3e..335d3861d9d 100755 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java @@ -5,7 +5,6 @@ import com.yahoo.searchlib.rankingexpression.ExpressionFunction; import com.yahoo.searchlib.rankingexpression.RankingExpression; import com.yahoo.searchlib.rankingexpression.Reference; import com.yahoo.searchlib.rankingexpression.evaluation.Context; -import com.yahoo.searchlib.rankingexpression.evaluation.StringValue; import com.yahoo.searchlib.rankingexpression.evaluation.Value; import com.yahoo.tensor.TensorType; import com.yahoo.tensor.evaluation.TypeContext; @@ -13,7 +12,7 @@ import com.yahoo.tensor.evaluation.TypeContext; import java.util.ArrayDeque; import java.util.Deque; import java.util.List; -import java.util.Optional; +import java.util.Map; /** * A node referring either to a value in the context or to a named ranking expression function. @@ -84,13 +83,25 @@ public final class ReferenceNode extends CompositeNode { if (path.contains(myPath)) throw new IllegalStateException("Cycle in ranking expression function: " + path); path.addLast(myPath); - ExpressionFunction.Instance instance = function.expand(context, getArguments().expressions(), path); + + String functionName = getName(); + String functionPropertyName = RankingExpression.propertyName(functionName); + boolean alreadySerialized = context.serializedFunctions().containsKey(functionPropertyName); + + if ( ! alreadySerialized || getArguments().size() > 0) { + ExpressionFunction.Instance instance = function.expand(context, getArguments().expressions(), path); + functionName = instance.getName(); + + context.addFunctionSerialization(RankingExpression.propertyName(functionName), instance.getExpressionString()); + for (Map.Entry<String, TensorType> argumentType : function.argumentTypes().entrySet()) + context.addArgumentTypeSerialization(functionName, argumentType.getKey(), argumentType.getValue()); + if (function.returnType().isPresent()) + context.addFunctionTypeSerialization(functionName, function.returnType().get()); + } path.removeLast(); - context.addFunctionSerialization(RankingExpression.propertyName(instance.getName()), instance.getExpressionString()); - return string.append("rankingExpression(").append(instance.getName()).append(')'); + return string.append("rankingExpression(").append(functionName).append(')'); } - // Not resolved in this context: output as-is return reference.toString(string, context, path, parent); } diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java index d7807caa2b6..92889d6607b 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java @@ -95,6 +95,12 @@ public class SerializationContext extends FunctionReferenceContext { return new SerializationContext(functions(), bindings, this.serializedFunctions); } + /** Returns a fresh context without bindings */ + @Override + public SerializationContext withoutBindings() { + return new SerializationContext(functions(), null, this.serializedFunctions); + } + public Map<String, String> serializedFunctions() { return serializedFunctions; } } diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java index 6e1cdf52158..befe2179dc1 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java @@ -333,10 +333,16 @@ public class TensorFunctionNode extends CompositeNode { /** Returns a new context with the bindings replaced by the given bindings */ @Override public ExpressionToStringContext withBindings(Map<String, String> bindings) { - return new ExpressionToStringContext(new SerializationContext(wrappedSerializationContext.functions().values(), bindings), - wrappedToStringContext, path, parent); + SerializationContext serializationContext = new SerializationContext(functions(), bindings, serializedFunctions()); + return new ExpressionToStringContext(serializationContext, wrappedToStringContext, path, parent); } + /** Returns a fresh context without bindings */ + @Override + public SerializationContext withoutBindings() { + SerializationContext serializationContext = new SerializationContext(functions(), null, serializedFunctions()); + return new ExpressionToStringContext(serializationContext, null, path, parent); + } } /** Turns an EvaluationContext into a Context */ diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java index a541eac2421..fed4f60e983 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java @@ -1,7 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchlib.rankingexpression.transform; -import com.yahoo.searchlib.rankingexpression.evaluation.TensorValue; +import com.yahoo.searchlib.rankingexpression.Reference; import com.yahoo.searchlib.rankingexpression.evaluation.Value; import com.yahoo.searchlib.rankingexpression.rule.CompositeNode; import com.yahoo.searchlib.rankingexpression.rule.ConstantNode; @@ -28,8 +28,15 @@ public class ConstantDereferencer extends ExpressionTransformer<TransformContext return node; } + /** Returns true if the given reference is an attribute, constant or query feature */ + private static boolean isSimpleFeature(Reference reference) { + if ( ! reference.isSimple()) return false; + String name = reference.name(); + return name.equals("attribute") || name.equals("constant") || name.equals("query"); + } + private ExpressionNode transformFeature(ReferenceNode node, TransformContext context) { - if (!node.getArguments().isEmpty()) + if ( ! node.getArguments().isEmpty() && ! isSimpleFeature(node.reference())) return transformArguments(node, context); else return transformConstantReference(node, context); @@ -44,7 +51,14 @@ public class ConstantDereferencer extends ExpressionTransformer<TransformContext } private ExpressionNode transformConstantReference(ReferenceNode node, TransformContext context) { - Value value = context.constants().get(node.getName()); + String name = node.getName(); + if (node.reference().name().equals("constant")) { + ExpressionNode arg = node.getArguments().expressions().get(0); + if (arg instanceof ReferenceNode) { + name = ((ReferenceNode)arg).getName(); + } + } + Value value = context.constants().get(name); // works if "constant(...)" is added if (value == null || value.type().rank() > 0) { return node; // not a number constant reference } |