This is an automated email from the ASF dual-hosted git repository.

richardstartin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new cfce5e1c7e vectorize predicate evaluation (#8759)
cfce5e1c7e is described below

commit cfce5e1c7ec650f08059fb4c31b199a75f5c677f
Author: Richard Startin <rich...@startree.ai>
AuthorDate: Tue May 24 14:41:44 2022 +0200

    vectorize predicate evaluation (#8759)
    
    * vectorize predicate evaluation
    
    * explain why applySV is reimplemented, don't mutate values for now
    
    * add benchmark for filtered scan
---
 .../dociditerators/SVScanDocIdIterator.java        | 67 ++++++++++++++++--
 .../predicate/EqualsPredicateEvaluatorFactory.java | 65 ++++++++++++++++++
 .../FSTBasedRegexpPredicateEvaluatorFactory.java   | 13 ++++
 .../predicate/InPredicateEvaluatorFactory.java     | 65 ++++++++++++++++++
 .../NotEqualsPredicateEvaluatorFactory.java        | 65 ++++++++++++++++++
 .../predicate/NotInPredicateEvaluatorFactory.java  | 65 ++++++++++++++++++
 .../filter/predicate/PredicateEvaluator.java       | 80 ++++++++++++++++++++++
 .../predicate/RangePredicateEvaluatorFactory.java  | 65 ++++++++++++++++++
 .../RegexpLikePredicateEvaluatorFactory.java       | 13 ++++
 .../org/apache/pinot/perf/BenchmarkQueries.java    |  6 +-
 10 files changed, 498 insertions(+), 6 deletions(-)

diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/dociditerators/SVScanDocIdIterator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/dociditerators/SVScanDocIdIterator.java
index d386f05caa..d462b3b6ed 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/dociditerators/SVScanDocIdIterator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/dociditerators/SVScanDocIdIterator.java
@@ -82,13 +82,13 @@ public final class SVScanDocIdIterator implements 
ScanBasedDocIdIterator {
     int[] buffer = new int[OPTIMAL_ITERATOR_BATCH_SIZE];
     while (docIdIterator.hasNext()) {
       int limit = docIdIterator.nextBatch(buffer);
-      for (int i = 0; i < limit; i++) {
-        int nextDocId = buffer[i];
-        _numEntriesScanned++;
-        if (_valueMatcher.doesValueMatch(nextDocId)) {
-          result.add(nextDocId);
+      if (limit > 0) {
+        int firstMismatch = _valueMatcher.matchValues(limit, buffer);
+        for (int i = 0; i < firstMismatch; i++) {
+          result.add(buffer[i]);
         }
       }
+      _numEntriesScanned += limit;
     }
     return result.get();
   }
@@ -129,46 +129,103 @@ public final class SVScanDocIdIterator implements 
ScanBasedDocIdIterator {
      * Returns {@code true} if the value for the given document id matches the 
predicate, {@code false} Otherwise.
      */
     boolean doesValueMatch(int docId);
+
+    /**
+     * Filters out non matching values and compacts matching docIds in the 
start of the array.
+     * @param limit how much of the input to read
+     * @param docIds the docIds to match - may be modified by this method so 
take a copy if necessary.
+     * @return the index in the array of the first non-matching element - all 
elements before this index match.
+     */
+    default int matchValues(int limit, int[] docIds) {
+      int matchCount = 0;
+      for (int i = 0; i < limit; i++) {
+        int docId = docIds[i];
+        if (doesValueMatch(docId)) {
+          docIds[matchCount++] = docId;
+        }
+      }
+      return matchCount;
+    }
   }
 
   private class DictIdMatcher implements ValueMatcher {
 
+    private final int[] _buffer = new int[OPTIMAL_ITERATOR_BATCH_SIZE];
+
     @Override
     public boolean doesValueMatch(int docId) {
       return _predicateEvaluator.applySV(_reader.getDictId(docId, 
_readerContext));
     }
+
+    @Override
+    public int matchValues(int limit, int[] docIds) {
+      _reader.readDictIds(docIds, limit, _buffer, _readerContext);
+      return _predicateEvaluator.applySV(limit, docIds, _buffer);
+    }
   }
 
   private class IntMatcher implements ValueMatcher {
 
+    private final int[] _buffer = new int[OPTIMAL_ITERATOR_BATCH_SIZE];
+
     @Override
     public boolean doesValueMatch(int docId) {
       return _predicateEvaluator.applySV(_reader.getInt(docId, 
_readerContext));
     }
+
+    @Override
+    public int matchValues(int limit, int[] docIds) {
+      _reader.readValuesSV(docIds, limit, _buffer, _readerContext);
+      return _predicateEvaluator.applySV(limit, docIds, _buffer);
+    }
   }
 
   private class LongMatcher implements ValueMatcher {
 
+    private final long[] _buffer = new long[OPTIMAL_ITERATOR_BATCH_SIZE];
+
     @Override
     public boolean doesValueMatch(int docId) {
       return _predicateEvaluator.applySV(_reader.getLong(docId, 
_readerContext));
     }
+
+    @Override
+    public int matchValues(int limit, int[] docIds) {
+      _reader.readValuesSV(docIds, limit, _buffer, _readerContext);
+      return _predicateEvaluator.applySV(limit, docIds, _buffer);
+    }
   }
 
   private class FloatMatcher implements ValueMatcher {
 
+    private final float[] _buffer = new float[OPTIMAL_ITERATOR_BATCH_SIZE];
+
     @Override
     public boolean doesValueMatch(int docId) {
       return _predicateEvaluator.applySV(_reader.getFloat(docId, 
_readerContext));
     }
+
+    @Override
+    public int matchValues(int limit, int[] docIds) {
+      _reader.readValuesSV(docIds, limit, _buffer, _readerContext);
+      return _predicateEvaluator.applySV(limit, docIds, _buffer);
+    }
   }
 
   private class DoubleMatcher implements ValueMatcher {
 
+    private final double[] _buffer = new double[OPTIMAL_ITERATOR_BATCH_SIZE];
+
     @Override
     public boolean doesValueMatch(int docId) {
       return _predicateEvaluator.applySV(_reader.getDouble(docId, 
_readerContext));
     }
+
+    @Override
+    public int matchValues(int limit, int[] docIds) {
+      _reader.readValuesSV(docIds, limit, _buffer, _readerContext);
+      return _predicateEvaluator.applySV(limit, docIds, _buffer);
+    }
   }
 
   private class BigDecimalMatcher implements ValueMatcher {
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/EqualsPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/EqualsPredicateEvaluatorFactory.java
index 71761c93d1..6df3d89b54 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/EqualsPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/EqualsPredicateEvaluatorFactory.java
@@ -106,6 +106,19 @@ public class EqualsPredicateEvaluatorFactory {
       return _matchingDictId == dictId;
     }
 
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
+
     @Override
     public int[] getMatchingDictIds() {
       return _matchingDictIds;
@@ -129,6 +142,19 @@ public class EqualsPredicateEvaluatorFactory {
     public boolean applySV(int value) {
       return _matchingValue == value;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class LongRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -148,6 +174,19 @@ public class EqualsPredicateEvaluatorFactory {
     public boolean applySV(long value) {
       return (_matchingValue == value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, long[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        long value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class FloatRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -167,6 +206,19 @@ public class EqualsPredicateEvaluatorFactory {
     public boolean applySV(float value) {
       return _matchingValue == value;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, float[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        float value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class DoubleRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -186,6 +238,19 @@ public class EqualsPredicateEvaluatorFactory {
     public boolean applySV(double value) {
       return _matchingValue == value;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, double[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        double value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class BigDecimalRawValueBasedEqPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/FSTBasedRegexpPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/FSTBasedRegexpPredicateEvaluatorFactory.java
index 2be5a94a24..b1a0559a92 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/FSTBasedRegexpPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/FSTBasedRegexpPredicateEvaluatorFactory.java
@@ -76,6 +76,19 @@ public class FSTBasedRegexpPredicateEvaluatorFactory {
       return _dictIds.contains(dictId);
     }
 
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
+
     @Override
     public int[] getMatchingDictIds() {
       return _dictIds.toArray();
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactory.java
index 1acace2a89..4724fefbaf 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactory.java
@@ -179,6 +179,19 @@ public class InPredicateEvaluatorFactory {
       }
       return _matchingDictIds;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class IntRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -198,6 +211,19 @@ public class InPredicateEvaluatorFactory {
     public boolean applySV(int value) {
       return _matchingValues.contains(value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class LongRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -217,6 +243,19 @@ public class InPredicateEvaluatorFactory {
     public boolean applySV(long value) {
       return _matchingValues.contains(value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, long[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        long value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class FloatRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -236,6 +275,19 @@ public class InPredicateEvaluatorFactory {
     public boolean applySV(float value) {
       return _matchingValues.contains(value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, float[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        float value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class DoubleRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -255,6 +307,19 @@ public class InPredicateEvaluatorFactory {
     public boolean applySV(double value) {
       return _matchingValues.contains(value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, double[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        double value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class BigDecimalRawValueBasedInPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotEqualsPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotEqualsPredicateEvaluatorFactory.java
index 01b0bc31c8..0c27596730 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotEqualsPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotEqualsPredicateEvaluatorFactory.java
@@ -109,6 +109,19 @@ public class NotEqualsPredicateEvaluatorFactory {
       return _nonMatchingDictId != dictId;
     }
 
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
+
     @Override
     public int[] getMatchingDictIds() {
       if (_matchingDictIds == null) {
@@ -154,6 +167,19 @@ public class NotEqualsPredicateEvaluatorFactory {
     public boolean applySV(int value) {
       return _nonMatchingValue != value;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class LongRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -173,6 +199,19 @@ public class NotEqualsPredicateEvaluatorFactory {
     public boolean applySV(long value) {
       return _nonMatchingValue != value;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, long[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        long value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class FloatRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -192,6 +231,19 @@ public class NotEqualsPredicateEvaluatorFactory {
     public boolean applySV(float value) {
       return _nonMatchingValue != value;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, float[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        float value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class DoubleRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -211,6 +263,19 @@ public class NotEqualsPredicateEvaluatorFactory {
     public boolean applySV(double value) {
       return _nonMatchingValue != value;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, double[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        double value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class BigDecimalRawValueBasedNeqPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotInPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotInPredicateEvaluatorFactory.java
index 9fe4696a6e..3407754ee9 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotInPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotInPredicateEvaluatorFactory.java
@@ -170,6 +170,19 @@ public class NotInPredicateEvaluatorFactory {
       return !_nonMatchingDictIdSet.contains(dictId);
     }
 
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
+
     @Override
     public int[] getMatchingDictIds() {
       if (_matchingDictIds == null) {
@@ -216,6 +229,19 @@ public class NotInPredicateEvaluatorFactory {
     public boolean applySV(int value) {
       return !_nonMatchingValues.contains(value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class LongRawValueBasedNotInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -235,6 +261,19 @@ public class NotInPredicateEvaluatorFactory {
     public boolean applySV(long value) {
       return !_nonMatchingValues.contains(value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, long[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        long value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class FloatRawValueBasedNotInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -254,6 +293,19 @@ public class NotInPredicateEvaluatorFactory {
     public boolean applySV(float value) {
       return !_nonMatchingValues.contains(value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, float[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        float value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class DoubleRawValueBasedNotInPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
@@ -273,6 +325,19 @@ public class NotInPredicateEvaluatorFactory {
     public boolean applySV(double value) {
       return !_nonMatchingValues.contains(value);
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, double[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        double value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   private static final class BigDecimalRawValueBasedNotInPredicateEvaluator
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/PredicateEvaluator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/PredicateEvaluator.java
index 0ba28dede3..8e54e130c9 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/PredicateEvaluator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/PredicateEvaluator.java
@@ -72,6 +72,26 @@ public interface PredicateEvaluator {
    */
   boolean applySV(int value);
 
+  /**
+   * Apply the predicate to a batch of single-value entries.
+   * Compact matching entries into the prefix of the docIds array.
+   *
+   * @param limit How much of the input to consume.
+   * @param docIds The docIds associated with the values - may be modified by 
invocation.
+   * @param values Batch of dictionary ids or raw values.
+   * @return the index of the first non-matching entry.
+   */
+  default int applySV(int limit, int[] docIds, int[] values) {
+    int matches = 0;
+    for (int i = 0; i < limit; i++) {
+      int value = values[i];
+      if (applySV(value)) {
+        docIds[matches++] = docIds[i];
+      }
+    }
+    return matches;
+  }
+
   /**
    * Apply a multi-value entry to the predicate.
    *
@@ -117,6 +137,26 @@ public interface PredicateEvaluator {
    */
   boolean applySV(long value);
 
+  /**
+   * Apply the predicate to a batch of single-value entries.
+   * Compact matching entries into the prefix of the docIds array.
+   *
+   * @param limit How much of the input to consume.
+   * @param docIds The docIds associated with the values - may be modified by 
invocation.
+   * @param values Batch of raw values - may be modified by invocation.
+   * @return the index of the first non-matching entry.
+   */
+  default int applySV(int limit, int[] docIds, long[] values) {
+    int matches = 0;
+    for (int i = 0; i < limit; i++) {
+      long value = values[i];
+      if (applySV(value)) {
+        docIds[matches++] = docIds[i];
+      }
+    }
+    return matches;
+  }
+
   /**
    * Apply a multi-value entry to the predicate.
    *
@@ -134,6 +174,26 @@ public interface PredicateEvaluator {
    */
   boolean applySV(float value);
 
+  /**
+   * Apply the predicate to a batch of single-value entries.
+   * Compact matching entries into the prefix of the docIds array.
+   *
+   * @param limit How much of the input to consume.
+   * @param docIds The docIds associated with the values - may be modified by 
invocation.
+   * @param values Batch of raw values - may be modified by invocation.
+   * @return the index of the first non-matching entry.
+   */
+  default int applySV(int limit, int[] docIds, float[] values) {
+    int matches = 0;
+    for (int i = 0; i < limit; i++) {
+      float value = values[i];
+      if (applySV(value)) {
+        docIds[matches++] = docIds[i];
+      }
+    }
+    return matches;
+  }
+
   /**
    * Apply a multi-value entry to the predicate.
    *
@@ -151,6 +211,26 @@ public interface PredicateEvaluator {
    */
   boolean applySV(double value);
 
+  /**
+   * Apply the predicate to a batch of single-value entries.
+   * Compact matching entries into the prefix of the docIds array.
+   *
+   * @param limit How much of the input to consume.
+   * @param docIds The docIds associated with the values - may be modified by 
invocation.
+   * @param values Batch of raw values - may be modified by invocation.
+   * @return the index of the first non-matching entry.
+   */
+  default int applySV(int limit, int[] docIds, double[] values) {
+    int matches = 0;
+    for (int i = 0; i < limit; i++) {
+      double value = values[i];
+      if (applySV(value)) {
+        docIds[matches++] = docIds[i];
+      }
+    }
+    return matches;
+  }
+
   /**
    * Apply a multi-value entry to the predicate.
    *
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/RangePredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/RangePredicateEvaluatorFactory.java
index b2e71270a5..151ab5f941 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/RangePredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/RangePredicateEvaluatorFactory.java
@@ -177,6 +177,19 @@ public class RangePredicateEvaluatorFactory {
       return _startDictId <= dictId && _endDictId > dictId;
     }
 
+    @Override
+    public int applySV(int limit, int[] docIds, int[] dictIds) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int dictId = dictIds[i];
+        if (applySV(dictId)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
+
     @Override
     public int getNumMatchingDictIds() {
       return _numMatchingDictIds;
@@ -309,6 +322,19 @@ public class RangePredicateEvaluatorFactory {
     public boolean applySV(int value) {
       return value >= _inclusiveLowerBound && value <= _inclusiveUpperBound;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   public static final class LongRawValueBasedRangePredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -349,6 +375,19 @@ public class RangePredicateEvaluatorFactory {
     public boolean applySV(long value) {
       return value >= _inclusiveLowerBound && value <= _inclusiveUpperBound;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, long[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        long value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   public static final class FloatRawValueBasedRangePredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -389,6 +428,19 @@ public class RangePredicateEvaluatorFactory {
     public boolean applySV(float value) {
       return value >= _inclusiveLowerBound && value <= _inclusiveUpperBound;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, float[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        float value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   public static final class DoubleRawValueBasedRangePredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
@@ -429,6 +481,19 @@ public class RangePredicateEvaluatorFactory {
     public boolean applySV(double value) {
       return value >= _inclusiveLowerBound && value <= _inclusiveUpperBound;
     }
+
+    @Override
+    public int applySV(int limit, int[] docIds, double[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        double value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
   }
 
   public static final class BigDecimalRawValueBasedRangePredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/RegexpLikePredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/RegexpLikePredicateEvaluatorFactory.java
index f245b54d89..a3af9de194 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/RegexpLikePredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/RegexpLikePredicateEvaluatorFactory.java
@@ -79,6 +79,19 @@ public class RegexpLikePredicateEvaluatorFactory {
       return _matcher.reset(_dictionary.getStringValue(dictId)).find();
     }
 
+    @Override
+    public int applySV(int limit, int[] docIds, int[] values) {
+      // reimplemented here to ensure applySV can be inlined
+      int matches = 0;
+      for (int i = 0; i < limit; i++) {
+        int value = values[i];
+        if (applySV(value)) {
+          docIds[matches++] = docIds[i];
+        }
+      }
+      return matches;
+    }
+
     @Override
     public int[] getMatchingDictIds() {
       if (_matchingDictIds == null) {
diff --git 
a/pinot-perf/src/main/java/org/apache/pinot/perf/BenchmarkQueries.java 
b/pinot-perf/src/main/java/org/apache/pinot/perf/BenchmarkQueries.java
index f1059b94d9..32696caf5f 100644
--- a/pinot-perf/src/main/java/org/apache/pinot/perf/BenchmarkQueries.java
+++ b/pinot-perf/src/main/java/org/apache/pinot/perf/BenchmarkQueries.java
@@ -122,6 +122,9 @@ public class BenchmarkQueries extends BaseQueriesTest {
   public static final String NO_INDEX_LIKE_QUERY = "SELECT RAW_INT_COL FROM 
MyTable "
       + "WHERE NO_INDEX_STRING_COL LIKE '%foo%'";
 
+  public static final String FILTERING_BITMAP_SCAN_QUERY = "SELECT RAW_INT_COL 
FROM MyTable "
+      + "WHERE INT_COL = 1 AND RAW_INT_COL IN (0, 1, 2)";
+
   public static final String MULTI_GROUP_BY_ORDER_BY = "SELECT 
NO_INDEX_STRING_COL,INT_COL,COUNT(*) "
       + "FROM MyTable GROUP BY NO_INDEX_STRING_COL,INT_COL ORDER BY 
NO_INDEX_STRING_COL, INT_COL ASC";
 
@@ -168,7 +171,8 @@ public class BenchmarkQueries extends BaseQueriesTest {
       MULTI_GROUP_BY_WITH_RAW_QUERY, MULTI_GROUP_BY_WITH_RAW_QUERY_2, 
FILTERED_QUERY, NON_FILTERED_QUERY,
       SUM_QUERY, NO_INDEX_LIKE_QUERY, MULTI_GROUP_BY_ORDER_BY, 
MULTI_GROUP_BY_ORDER_BY_LOW_HIGH, TIME_GROUP_BY,
       RAW_COLUMN_SUMMARY_STATS, COUNT_OVER_BITMAP_INDEX_IN, 
COUNT_OVER_BITMAP_INDEXES,
-      COUNT_OVER_BITMAP_AND_SORTED_INDEXES, COUNT_OVER_BITMAP_INDEX_EQUALS, 
STARTREE_SUM_QUERY, STARTREE_FILTER_QUERY
+      COUNT_OVER_BITMAP_AND_SORTED_INDEXES, COUNT_OVER_BITMAP_INDEX_EQUALS, 
STARTREE_SUM_QUERY, STARTREE_FILTER_QUERY,
+      FILTERING_BITMAP_SCAN_QUERY
   })
   String _query;
   private IndexSegment _indexSegment;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org
For additional commands, e-mail: commits-h...@pinot.apache.org

Reply via email to