From 07251dc25ce723267077667821e3416ab56fe8f1 Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Sat, 10 Nov 2018 17:33:27 -0800 Subject: [PATCH 1/5] Optimization for expressions that hit a single long column. There was previously a single-long-input optimization that applied only to the time column. These have been combined together. Also adds type-specific value caching to ExprEval, which allowed simplifying the SingleLongInputCachingExpressionColumnValueSelector code. --- .../ExpressionSelectorBenchmark.java | 75 ++++++++++++- .../benchmark/datagen/SegmentGenerator.java | 4 + .../org/apache/druid/math/expr/ExprEval.java | 95 +++++++++++++--- .../segment/virtual/ExpressionSelectors.java | 8 +- ...tCachingExpressionColumnValueSelector.java | 106 +++++++++--------- 5 files changed, 210 insertions(+), 78 deletions(-) diff --git a/benchmarks/src/main/java/org/apache/druid/benchmark/ExpressionSelectorBenchmark.java b/benchmarks/src/main/java/org/apache/druid/benchmark/ExpressionSelectorBenchmark.java index 5b6d8a3d9c71..f1619c58bf02 100644 --- a/benchmarks/src/main/java/org/apache/druid/benchmark/ExpressionSelectorBenchmark.java +++ b/benchmarks/src/main/java/org/apache/druid/benchmark/ExpressionSelectorBenchmark.java @@ -80,7 +80,16 @@ public void setup() { final BenchmarkSchemaInfo schemaInfo = new BenchmarkSchemaInfo( ImmutableList.of( - BenchmarkColumnSchema.makeNormal("n", ValueType.LONG, false, 1, 0d, 0d, 10000d, false), + BenchmarkColumnSchema.makeZipf( + "n", + ValueType.LONG, + false, + 1, + 0d, + 1000, + 10000, + 3d + ), BenchmarkColumnSchema.makeZipf( "s", ValueType.STRING, @@ -312,6 +321,70 @@ public void strlenUsingExtractionFn(Blackhole blackhole) blackhole.consume(results); } + @Benchmark + public void arithmeticOnLong(Blackhole blackhole) + { + final Sequence cursors = new QueryableIndexStorageAdapter(index).makeCursors( + null, + index.getDataInterval(), + VirtualColumns.create( + ImmutableList.of( + new ExpressionVirtualColumn( + "v", + "n + 1", + ValueType.LONG, + TestExprMacroTable.INSTANCE + ) + ) + ), + Granularities.ALL, + false, + null + ); + + final List results = cursors + .map(cursor -> { + final ColumnValueSelector selector = cursor.getColumnSelectorFactory().makeColumnValueSelector("v"); + consumeLong(cursor, selector, blackhole); + return null; + }) + .toList(); + + blackhole.consume(results); + } + + @Benchmark + public void stringConcatAndCompareOnLong(Blackhole blackhole) + { + final Sequence cursors = new QueryableIndexStorageAdapter(index).makeCursors( + null, + index.getDataInterval(), + VirtualColumns.create( + ImmutableList.of( + new ExpressionVirtualColumn( + "v", + "concat(n, ' is my favorite number') == '3 is my favorite number'", + ValueType.LONG, + TestExprMacroTable.INSTANCE + ) + ) + ), + Granularities.ALL, + false, + null + ); + + final List results = cursors + .map(cursor -> { + final ColumnValueSelector selector = cursor.getColumnSelectorFactory().makeColumnValueSelector("v"); + consumeLong(cursor, selector, blackhole); + return null; + }) + .toList(); + + blackhole.consume(results); + } + private void consumeDimension(final Cursor cursor, final DimensionSelector selector, final Blackhole blackhole) { if (selector.getValueCardinality() >= 0) { diff --git a/benchmarks/src/main/java/org/apache/druid/benchmark/datagen/SegmentGenerator.java b/benchmarks/src/main/java/org/apache/druid/benchmark/datagen/SegmentGenerator.java index 1fb709ec44cd..46904205d257 100644 --- a/benchmarks/src/main/java/org/apache/druid/benchmark/datagen/SegmentGenerator.java +++ b/benchmarks/src/main/java/org/apache/druid/benchmark/datagen/SegmentGenerator.java @@ -27,6 +27,7 @@ import org.apache.druid.data.input.InputRow; import org.apache.druid.data.input.impl.DimensionSchema; import org.apache.druid.data.input.impl.DimensionsSpec; +import org.apache.druid.data.input.impl.DoubleDimensionSchema; import org.apache.druid.data.input.impl.FloatDimensionSchema; import org.apache.druid.data.input.impl.LongDimensionSchema; import org.apache.druid.data.input.impl.StringDimensionSchema; @@ -99,6 +100,9 @@ public QueryableIndex generate( case LONG: dimensions.add(new LongDimensionSchema(columnSchema.getName())); break; + case DOUBLE: + dimensions.add(new DoubleDimensionSchema(columnSchema.getName())); + break; case FLOAT: dimensions.add(new FloatDimensionSchema(columnSchema.getName())); break; diff --git a/core/src/main/java/org/apache/druid/math/expr/ExprEval.java b/core/src/main/java/org/apache/druid/math/expr/ExprEval.java index 60009122de19..6a9a164a8177 100644 --- a/core/src/main/java/org/apache/druid/math/expr/ExprEval.java +++ b/core/src/main/java/org/apache/druid/math/expr/ExprEval.java @@ -30,6 +30,18 @@ */ public abstract class ExprEval { + // Cached values of various types. Protected so they can be used by subclasses. + protected boolean intValueValid = false; + protected boolean longValueValid = false; + protected boolean doubleValueValid = false; + protected boolean stringValueValid = false; + protected boolean booleanValueValid = false; + protected int intValue; + protected long longValue; + protected double doubleValue; + protected String stringValue; + protected boolean booleanValue; + public static ExprEval ofLong(@Nullable Number longValue) { return new LongExprEval(longValue); @@ -89,7 +101,7 @@ public static ExprEval bestEffortOf(@Nullable Object val) @Nullable final T value; - private ExprEval(T value) + private ExprEval(@Nullable T value) { this.value = value; } @@ -115,7 +127,17 @@ public Object value() @Nullable public String asString() { - return value == null ? null : String.valueOf(value); + if (!stringValueValid) { + if (value == null) { + stringValue = null; + } else { + stringValue = String.valueOf(value); + } + + stringValueValid = true; + } + + return stringValue; } public abstract boolean asBoolean(); @@ -126,7 +148,6 @@ public String asString() private abstract static class NumericExprEval extends ExprEval { - private NumericExprEval(@Nullable Number value) { super(value); @@ -263,9 +284,48 @@ public final ExprType type() } @Override - public final int asInt() + public int asInt() { - Number number = asNumber(); + if (!intValueValid) { + intValue = computeInt(); + intValueValid = true; + } + + return intValue; + } + + @Override + public long asLong() + { + if (!longValueValid) { + longValue = computeLong(); + longValueValid = true; + } + + return longValue; + } + + @Override + public double asDouble() + { + if (!doubleValueValid) { + doubleValue = computeDouble(); + doubleValueValid = true; + } + + return doubleValue; + } + + @Nullable + @Override + public String asString() + { + return value; + } + + private int computeInt() + { + Number number = computeNumber(); if (number == null) { assert NullHandling.replaceWithDefault(); return 0; @@ -273,10 +333,9 @@ public final int asInt() return number.intValue(); } - @Override - public final long asLong() + private long computeLong() { - Number number = asNumber(); + Number number = computeNumber(); if (number == null) { assert NullHandling.replaceWithDefault(); return 0L; @@ -284,10 +343,9 @@ public final long asLong() return number.longValue(); } - @Override - public final double asDouble() + private double computeDouble() { - Number number = asNumber(); + Number number = computeNumber(); if (number == null) { assert NullHandling.replaceWithDefault(); return 0.0d; @@ -296,7 +354,7 @@ public final double asDouble() } @Nullable - private Number asNumber() + private Number computeNumber() { if (value == null) { return null; @@ -321,13 +379,18 @@ private Number asNumber() @Override public boolean isNumericNull() { - return asNumber() == null; + return computeNumber() == null; } @Override public final boolean asBoolean() { - return Evals.asBoolean(value); + if (!booleanValueValid) { + booleanValue = Evals.asBoolean(value); + booleanValueValid = true; + } + + return booleanValue; } @Override @@ -335,9 +398,9 @@ public final ExprEval castTo(ExprType castTo) { switch (castTo) { case DOUBLE: - return ExprEval.ofDouble(asNumber()); + return ExprEval.ofDouble(computeNumber()); case LONG: - return ExprEval.ofLong(asNumber()); + return ExprEval.ofLong(computeNumber()); case STRING: return this; } diff --git a/processing/src/main/java/org/apache/druid/segment/virtual/ExpressionSelectors.java b/processing/src/main/java/org/apache/druid/segment/virtual/ExpressionSelectors.java index 14429032ceb0..a2161beb4593 100644 --- a/processing/src/main/java/org/apache/druid/segment/virtual/ExpressionSelectors.java +++ b/processing/src/main/java/org/apache/druid/segment/virtual/ExpressionSelectors.java @@ -39,7 +39,6 @@ import org.apache.druid.segment.DimensionSelector; import org.apache.druid.segment.NilColumnValueSelector; import org.apache.druid.segment.column.ColumnCapabilities; -import org.apache.druid.segment.column.ColumnHolder; import org.apache.druid.segment.column.ValueType; import org.apache.druid.segment.data.IndexedInts; @@ -137,11 +136,10 @@ public static ColumnValueSelector makeExprEvalSelector( final String column = Iterables.getOnlyElement(columns); final ColumnCapabilities capabilities = columnSelectorFactory.getColumnCapabilities(column); - if (column.equals(ColumnHolder.TIME_COLUMN_NAME)) { - // Optimization for expressions that hit the __time column and nothing else. - // May be worth applying this optimization to all long columns? + if (capabilities != null && capabilities.getType() == ValueType.LONG) { + // Optimization for expressions that hit one long column and nothing else. return new SingleLongInputCachingExpressionColumnValueSelector( - columnSelectorFactory.makeColumnValueSelector(ColumnHolder.TIME_COLUMN_NAME), + columnSelectorFactory.makeColumnValueSelector(column), expression ); } else if (capabilities != null diff --git a/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java b/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java index f3ffe8318612..7cc2070b6dde 100644 --- a/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java +++ b/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java @@ -20,6 +20,7 @@ package org.apache.druid.segment.virtual; import com.google.common.base.Preconditions; +import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import org.apache.druid.java.util.common.ISE; import org.apache.druid.math.expr.Expr; import org.apache.druid.math.expr.ExprEval; @@ -28,6 +29,7 @@ import org.apache.druid.segment.ColumnValueSelector; import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * Like {@link ExpressionColumnValueSelector}, but caches the most recently computed value and re-uses it in the case @@ -35,26 +37,18 @@ */ public class SingleLongInputCachingExpressionColumnValueSelector implements ColumnValueSelector { - enum Validity - { - NONE, - DOUBLE, - LONG, - EVAL - } + private static final int CACHE_SIZE = 1000; private final ColumnValueSelector selector; private final Expr expression; - private final SingleInputBindings bindings = new SingleInputBindings(); + private final LruEvalCache lruEvalCache; - // Last read input value + // Last read input value. private long lastInput; - // Last computed output values (validity determined by "validity" field) - private Validity validity = Validity.NONE; - private double lastDoubleOutput; - private long lastLongOutput; - private ExprEval lastEvalOutput; + // Last computed output value, or null if there is none. + @Nullable + private ExprEval lastOutput; public SingleLongInputCachingExpressionColumnValueSelector( final ColumnValueSelector selector, @@ -68,6 +62,7 @@ public SingleLongInputCachingExpressionColumnValueSelector( this.selector = Preconditions.checkNotNull(selector, "selector"); this.expression = Preconditions.checkNotNull(expression, "expression"); + this.lruEvalCache = new LruEvalCache(expression); } @Override @@ -80,59 +75,35 @@ public void inspectRuntimeShape(final RuntimeShapeInspector inspector) @Override public double getDouble() { - // No Assert for null handling as delegate selector already have it. - final long currentInput = selector.getLong(); - - if (lastInput == currentInput && validity == Validity.DOUBLE) { - return lastDoubleOutput; - } else { - final double output = eval(currentInput).asDouble(); - lastInput = currentInput; - lastDoubleOutput = output; - validity = Validity.DOUBLE; - return output; - } + return getObject().asDouble(); } @Override public float getFloat() { - // No Assert for null handling as delegate selector already have it. - return (float) getDouble(); + return (float) getObject().asDouble(); } @Override public long getLong() { - // No Assert for null handling as delegate selector already have it. - final long currentInput = selector.getLong(); - - if (lastInput == currentInput && validity == Validity.LONG) { - return lastLongOutput; - } else { - final long output = eval(currentInput).asLong(); - lastInput = currentInput; - lastLongOutput = output; - validity = Validity.LONG; - return output; - } + return getObject().asLong(); } @Nonnull @Override public ExprEval getObject() { - final long currentInput = selector.getLong(); - - if (lastInput == currentInput && validity == Validity.EVAL) { - return lastEvalOutput; - } else { - final ExprEval output = eval(currentInput); - lastInput = currentInput; - lastEvalOutput = output; - validity = Validity.EVAL; - return output; + // No assert for null handling, as the delegate selector already has it. + final long input = selector.getLong(); + final boolean cached = input == lastInput && lastOutput != null; + + if (!cached) { + lastOutput = lruEvalCache.compute(input); + lastInput = input; } + + return lastOutput; } @Override @@ -141,12 +112,6 @@ public Class classOfObject() return ExprEval.class; } - private ExprEval eval(final long value) - { - bindings.set(value); - return expression.eval(bindings); - } - @Override public boolean isNull() { @@ -155,4 +120,33 @@ public boolean isNull() // ExprEval.isNumericNull checks whether the parsed primitive value is null or not. return getObject().isNumericNull(); } + + public static class LruEvalCache + { + private final Expr expression; + private final SingleInputBindings bindings = new SingleInputBindings(); + private final Long2ObjectLinkedOpenHashMap m = new Long2ObjectLinkedOpenHashMap<>(CACHE_SIZE); + + public LruEvalCache(final Expr expression) + { + this.expression = expression; + } + + public ExprEval compute(final long n) + { + ExprEval value = m.getAndMoveToFirst(n); + + if (value == null) { + bindings.set(n); + value = expression.eval(bindings); + m.putAndMoveToFirst(n, value); + + if (m.size() > CACHE_SIZE) { + m.removeLast(); + } + } + + return value; + } + } } From daf7f58e2c39a8114f848545606c6b43e530a74d Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Sat, 10 Nov 2018 20:29:54 -0800 Subject: [PATCH 2/5] Add more benchmarks. --- .../ExpressionSelectorBenchmark.java | 70 +++++++++++++++++-- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/benchmarks/src/main/java/org/apache/druid/benchmark/ExpressionSelectorBenchmark.java b/benchmarks/src/main/java/org/apache/druid/benchmark/ExpressionSelectorBenchmark.java index f1619c58bf02..9953c0e3a40c 100644 --- a/benchmarks/src/main/java/org/apache/druid/benchmark/ExpressionSelectorBenchmark.java +++ b/benchmarks/src/main/java/org/apache/druid/benchmark/ExpressionSelectorBenchmark.java @@ -155,10 +155,7 @@ public void timeFloorUsingExpression(Blackhole blackhole) final List results = cursors .map(cursor -> { final ColumnValueSelector selector = cursor.getColumnSelectorFactory().makeColumnValueSelector("v"); - while (!cursor.isDone()) { - blackhole.consume(selector.getLong()); - cursor.advance(); - } + consumeLong(cursor, selector, blackhole); return null; }) .toList(); @@ -228,6 +225,71 @@ public void timeFloorUsingCursor(Blackhole blackhole) blackhole.consume(count); } + @Benchmark + public void timeFormatUsingExpression(Blackhole blackhole) + { + final Sequence cursors = new QueryableIndexStorageAdapter(index).makeCursors( + null, + index.getDataInterval(), + VirtualColumns.create( + ImmutableList.of( + new ExpressionVirtualColumn( + "v", + "timestamp_format(__time, 'yyyy-MM-dd')", + ValueType.STRING, + TestExprMacroTable.INSTANCE + ) + ) + ), + Granularities.ALL, + false, + null + ); + + final List results = cursors + .map(cursor -> { + final DimensionSelector selector = cursor.getColumnSelectorFactory().makeDimensionSelector( + DefaultDimensionSpec.of("v") + ); + consumeDimension(cursor, selector, blackhole); + return null; + }) + .toList(); + + blackhole.consume(results); + } + + @Benchmark + public void timeFormatUsingExtractionFn(Blackhole blackhole) + { + final Sequence cursors = new QueryableIndexStorageAdapter(index).makeCursors( + null, + index.getDataInterval(), + VirtualColumns.EMPTY, + Granularities.ALL, + false, + null + ); + + final List results = cursors + .map(cursor -> { + final DimensionSelector selector = cursor + .getColumnSelectorFactory() + .makeDimensionSelector( + new ExtractionDimensionSpec( + ColumnHolder.TIME_COLUMN_NAME, + "v", + new TimeFormatExtractionFn("yyyy-MM-dd", null, null, null, false) + ) + ); + consumeDimension(cursor, selector, blackhole); + return null; + }) + .toList(); + + blackhole.consume(results); + } + @Benchmark public void strlenUsingExpressionAsLong(Blackhole blackhole) { From 54844656d310c43db5794e47cf81e89ef1ff53af Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Sat, 10 Nov 2018 20:38:25 -0800 Subject: [PATCH 3/5] Don't use LRU cache for __time. --- .../segment/virtual/ExpressionSelectors.java | 4 +++- ...tCachingExpressionColumnValueSelector.java | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/processing/src/main/java/org/apache/druid/segment/virtual/ExpressionSelectors.java b/processing/src/main/java/org/apache/druid/segment/virtual/ExpressionSelectors.java index a2161beb4593..b0d49bad47bf 100644 --- a/processing/src/main/java/org/apache/druid/segment/virtual/ExpressionSelectors.java +++ b/processing/src/main/java/org/apache/druid/segment/virtual/ExpressionSelectors.java @@ -39,6 +39,7 @@ import org.apache.druid.segment.DimensionSelector; import org.apache.druid.segment.NilColumnValueSelector; import org.apache.druid.segment.column.ColumnCapabilities; +import org.apache.druid.segment.column.ColumnHolder; import org.apache.druid.segment.column.ValueType; import org.apache.druid.segment.data.IndexedInts; @@ -140,7 +141,8 @@ public static ColumnValueSelector makeExprEvalSelector( // Optimization for expressions that hit one long column and nothing else. return new SingleLongInputCachingExpressionColumnValueSelector( columnSelectorFactory.makeColumnValueSelector(column), - expression + expression, + !ColumnHolder.TIME_COLUMN_NAME.equals(column) // __time doesn't need an LRU cache since it is sorted. ); } else if (capabilities != null && capabilities.getType() == ValueType.STRING diff --git a/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java b/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java index 7cc2070b6dde..33a5d338a4a9 100644 --- a/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java +++ b/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java @@ -41,6 +41,9 @@ public class SingleLongInputCachingExpressionColumnValueSelector implements Colu private final ColumnValueSelector selector; private final Expr expression; + private final SingleInputBindings bindings = new SingleInputBindings(); + + @Nullable private final LruEvalCache lruEvalCache; // Last read input value. @@ -52,7 +55,8 @@ public class SingleLongInputCachingExpressionColumnValueSelector implements Colu public SingleLongInputCachingExpressionColumnValueSelector( final ColumnValueSelector selector, - final Expr expression + final Expr expression, + final boolean useLruCache ) { // Verify expression has just one binding. @@ -62,7 +66,7 @@ public SingleLongInputCachingExpressionColumnValueSelector( this.selector = Preconditions.checkNotNull(selector, "selector"); this.expression = Preconditions.checkNotNull(expression, "expression"); - this.lruEvalCache = new LruEvalCache(expression); + this.lruEvalCache = useLruCache ? new LruEvalCache(expression) : null; } @Override @@ -99,7 +103,13 @@ public ExprEval getObject() final boolean cached = input == lastInput && lastOutput != null; if (!cached) { - lastOutput = lruEvalCache.compute(input); + if (lruEvalCache == null) { + bindings.set(input); + lastOutput = expression.eval(bindings); + } else { + lastOutput = lruEvalCache.compute(input); + } + lastInput = input; } @@ -121,10 +131,9 @@ public boolean isNull() return getObject().isNumericNull(); } - public static class LruEvalCache + public class LruEvalCache { private final Expr expression; - private final SingleInputBindings bindings = new SingleInputBindings(); private final Long2ObjectLinkedOpenHashMap m = new Long2ObjectLinkedOpenHashMap<>(CACHE_SIZE); public LruEvalCache(final Expr expression) From 93a326426a53ad2fbbbeecf6b9a2b924c14eb6a5 Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Sun, 11 Nov 2018 02:15:05 -0800 Subject: [PATCH 4/5] Simplify a bit. --- .../org/apache/druid/math/expr/ExprEval.java | 24 ++++++++++--------- ...tCachingExpressionColumnValueSelector.java | 8 +------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/org/apache/druid/math/expr/ExprEval.java b/core/src/main/java/org/apache/druid/math/expr/ExprEval.java index 6a9a164a8177..2b649d471351 100644 --- a/core/src/main/java/org/apache/druid/math/expr/ExprEval.java +++ b/core/src/main/java/org/apache/druid/math/expr/ExprEval.java @@ -30,17 +30,9 @@ */ public abstract class ExprEval { - // Cached values of various types. Protected so they can be used by subclasses. - protected boolean intValueValid = false; - protected boolean longValueValid = false; - protected boolean doubleValueValid = false; - protected boolean stringValueValid = false; - protected boolean booleanValueValid = false; - protected int intValue; - protected long longValue; - protected double doubleValue; - protected String stringValue; - protected boolean booleanValue; + // Cached String values. Protected so they can be used by subclasses. + private boolean stringValueValid = false; + private String stringValue; public static ExprEval ofLong(@Nullable Number longValue) { @@ -268,6 +260,16 @@ public Expr toExpr() private static class StringExprEval extends ExprEval { + // Cached primitive values. + private boolean intValueValid = false; + private boolean longValueValid = false; + private boolean doubleValueValid = false; + private boolean booleanValueValid = false; + private int intValue; + private long longValue; + private double doubleValue; + private boolean booleanValue; + private static final StringExprEval OF_NULL = new StringExprEval(null); private Number numericVal; diff --git a/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java b/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java index 33a5d338a4a9..927fe4bd57cd 100644 --- a/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java +++ b/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java @@ -66,7 +66,7 @@ public SingleLongInputCachingExpressionColumnValueSelector( this.selector = Preconditions.checkNotNull(selector, "selector"); this.expression = Preconditions.checkNotNull(expression, "expression"); - this.lruEvalCache = useLruCache ? new LruEvalCache(expression) : null; + this.lruEvalCache = useLruCache ? new LruEvalCache() : null; } @Override @@ -133,14 +133,8 @@ public boolean isNull() public class LruEvalCache { - private final Expr expression; private final Long2ObjectLinkedOpenHashMap m = new Long2ObjectLinkedOpenHashMap<>(CACHE_SIZE); - public LruEvalCache(final Expr expression) - { - this.expression = expression; - } - public ExprEval compute(final long n) { ExprEval value = m.getAndMoveToFirst(n); From 0322fb65215bcceda2ad5cd05a38a9f300db76b3 Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Sun, 11 Nov 2018 17:17:33 -0800 Subject: [PATCH 5/5] Let the cache grow. --- .../SingleLongInputCachingExpressionColumnValueSelector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java b/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java index 927fe4bd57cd..fa002c022036 100644 --- a/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java +++ b/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java @@ -133,7 +133,7 @@ public boolean isNull() public class LruEvalCache { - private final Long2ObjectLinkedOpenHashMap m = new Long2ObjectLinkedOpenHashMap<>(CACHE_SIZE); + private final Long2ObjectLinkedOpenHashMap m = new Long2ObjectLinkedOpenHashMap<>(); public ExprEval compute(final long n) {