Commit e06dd2b
feat(selective): SIMD filterCache evaluation for dictionary index reading with filters (#17954)
Summary:
X-link: facebookincubator/nimble#916
Pull Request resolved: #17954
Dictionary-encoded string columns in the selective Nimble reader emit a `DictionaryVector` backed by a single alphabet merged across all chunks of a read range. A filter pushed down on such a column cannot be evaluated inside the encoding's per-row decode: the merged alphabet (and therefore the per-alphabet-index `filterCache`) is not known until every chunk has been read, and the inner encoding's `bulkScan` would apply a string filter directly to raw `int32` dictionary indices. The filter is therefore suppressed during the bulk `materializeIndices` read and applied post-hoc on the merged alphabet.
This diff replaces the previous in-encoding (`populateScanState` / framework `StringDictionaryColumnVisitor`) filter evaluation with that post-hoc path, makes it SIMD-accelerated, and removes the now-dead in-encoding code:
- Shared SIMD kernel. Add a free function `filterDictionaryRunSimd<kFilterOnly>(...)` in `velox/dwio/common/ColumnVisitors.h` that gathers each index's cached verdict from `filterCache`, resolves cache misses through the filter (recording the result back), and SIMD-compacts the passing rows (and, unless `kFilterOnly`, the passing indices). Nimble's `filterByCache` calls it directly. DWRF's `StringDictionaryColumnVisitor::processRun` is left unchanged; it still holds an equivalent inline loop, marked with a TODO to adopt the shared kernel in a follow-up diff (kept separate to isolate the DWRF change from this Nimble feature).
- Post-hoc filter in `StringColumnReader`. `readWithDictionary` saves and clears the scan-spec filter so the bulk index read runs, then `filterDictionaryIndices` applies the filter on the merged alphabet via `filterByCache`, compacting `rawValues_`/`outputRows_` to the passing rows. `ensureFilterCache` lazily sizes the per-alphabet-index cache, which grows and clears together with the alphabet.
- Output-layout null realignment. Pre-compacting `rawValues_`/`outputRows_` makes the framework's `compactScalarValues` a no-op (`rows.size() == numValues_`), which skips its null move, so `filterDictionaryIndices` realigns the result nulls itself in three cases: (1) no nulls — filter in place; (2) value filter rejects nulls — filter in place and mark the compacted output all-non-null; (3) IS NULL accepts nulls — merge null rows with the passing non-null rows in row order. `ensureWritableResultNulls` mirrors the framework's `shouldMoveNulls` by switching off the dense `returnReaderNulls_` fast path and allocating an output-indexed null bitmap.
- Delete dead code. With `StringColumnReader` the sole owner of dictionary filtering, the per-encoding `kHasFilter` branches and the `prepareResultNullsForDenseFilter` helper in `encodings/common/Encoding.h` (and their call sites in the `Constant`, `Dictionary`, `MainlyConstant`, and `RLE` encodings) are unreachable and removed, along with `StringColumnReader::populateScanState`.
Performance. On a simulated filter workload (`parallel_reader` over a dictionary-encoded string column, `l_returnflag='R'`, opt mode, `batch_size=1024`, concurrency 16, `read_count=500`, P50), the SIMD `filterCache` path reads at ~52 ms, versus ~70 ms for the parent diff's scalar per-row filter (−26%) and 130 ms for a no-dictionary flat read (−60%). The gain comes from evaluating the byte filter once per distinct dictionary value (`filterCache` memoization) and SIMD-gathering/compacting survivors, instead of testing the filter per row. (Parent/flat figures are from the 2026-06-05 A/B; the SIMD figure was reconfirmed on the current stack on 2026-06-13: P50 wall 52/52/54 ms across 3 runs.)
No behavior change for non-dictionary columns or for dictionary columns read without a pushed-down filter.
Reviewed By: Yuhta
Differential Revision: D102273283
fbshipit-source-id: 6ff65058a06af4be9f04056e6508062b3297793b1 parent 6577a09 commit e06dd2b
3 files changed
Lines changed: 405 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
617 | 617 | | |
618 | 618 | | |
619 | 619 | | |
620 | | - | |
621 | | - | |
622 | 620 | | |
623 | 621 | | |
624 | 622 | | |
| |||
1387 | 1385 | | |
1388 | 1386 | | |
1389 | 1387 | | |
| 1388 | + | |
| 1389 | + | |
| 1390 | + | |
| 1391 | + | |
| 1392 | + | |
1390 | 1393 | | |
1391 | 1394 | | |
1392 | 1395 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| |||
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
36 | 146 | | |
37 | 147 | | |
38 | 148 | | |
| |||
0 commit comments