diff --git a/presto-main/src/main/java/io/prestosql/metadata/MetadataManager.java b/presto-main/src/main/java/io/prestosql/metadata/MetadataManager.java index 8e697a0733033..5e1a4a5ff3cae 100644 --- a/presto-main/src/main/java/io/prestosql/metadata/MetadataManager.java +++ b/presto-main/src/main/java/io/prestosql/metadata/MetadataManager.java @@ -15,11 +15,15 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; +import com.google.common.util.concurrent.UncheckedExecutionException; import io.airlift.slice.Slice; import io.prestosql.Session; import io.prestosql.connector.CatalogName; @@ -195,6 +199,9 @@ public final class MetadataManager private final ResolvedFunctionDecoder functionDecoder; + private final LoadingCache operatorCache; + private final LoadingCache coercionCache; + @Inject public MetadataManager( FeaturesConfig featuresConfig, @@ -240,6 +247,23 @@ public MetadataManager( verifyTypes(); functionDecoder = new ResolvedFunctionDecoder(this::getType); + + operatorCache = CacheBuilder.newBuilder() + .maximumSize(1000) + .build(CacheLoader.from(key -> { + String name = mangleOperatorName(key.getOperatorType()); + return resolveFunction(QualifiedName.of(name), fromTypes(key.getArgumentTypes())); + })); + + coercionCache = CacheBuilder.newBuilder() + .maximumSize(1000) + .build(CacheLoader.from(key -> { + String name = mangleOperatorName(key.getOperatorType()); + Type fromType = key.getFromType(); + Type toType = key.getToType(); + Signature signature = new Signature(name, toType.getTypeSignature(), ImmutableList.of(fromType.getTypeSignature())); + return resolve(functionResolver.resolveCoercion(functions.get(QualifiedName.of(name)), signature)); + })); } public static MetadataManager createTestMetadataManager() @@ -1779,17 +1803,17 @@ public ResolvedFunction resolveOperator(OperatorType operatorType, List argumentTypes; + + private OperatorCacheKey(OperatorType operatorType, List argumentTypes) + { + this.operatorType = requireNonNull(operatorType, "operatorType is null"); + this.argumentTypes = ImmutableList.copyOf(requireNonNull(argumentTypes, "argumentTypes is null")); + } + + public OperatorType getOperatorType() + { + return operatorType; + } + + public List getArgumentTypes() + { + return argumentTypes; + } + + @Override + public int hashCode() + { + return Objects.hash(operatorType, argumentTypes); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) { + return true; + } + if (!(obj instanceof OperatorCacheKey)) { + return false; + } + OperatorCacheKey other = (OperatorCacheKey) obj; + return Objects.equals(this.operatorType, other.operatorType) && + Objects.equals(this.argumentTypes, other.argumentTypes); + } + } + + private static class CoercionCacheKey + { + private final OperatorType operatorType; + private final Type fromType; + private final Type toType; + + private CoercionCacheKey(OperatorType operatorType, Type fromType, Type toType) + { + this.operatorType = requireNonNull(operatorType, "operatorType is null"); + this.fromType = requireNonNull(fromType, "fromType is null"); + this.toType = requireNonNull(toType, "toType is null"); + } + + public OperatorType getOperatorType() + { + return operatorType; + } + + public Type getFromType() + { + return fromType; + } + + public Type getToType() + { + return toType; + } + + @Override + public int hashCode() + { + return Objects.hash(operatorType, fromType, toType); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) { + return true; + } + if (!(obj instanceof CoercionCacheKey)) { + return false; + } + CoercionCacheKey other = (CoercionCacheKey) obj; + return Objects.equals(this.operatorType, other.operatorType) && + Objects.equals(this.fromType, other.fromType) && + Objects.equals(this.toType, other.toType); + } + } }