|
1 | 1 | # ADR 0013: Compute primitives — masks, kernels, no-materialize contract |
2 | 2 |
|
3 | | -- **Status:** Accepted — §1 (Mask), §4 (Predicate), §2/§3 (filter/reduce kernels, a generic |
4 | | - streaming baseline plus a type-specialized boxing-free fast lane, behind a minimal `Compute` |
5 | | - entry point), §5 (`RowFilter` unified over `Predicate` — a `RowFilter.Column` binds a column to a |
6 | | - shared public `Predicate`; the same predicate is compiled against zone-map stats for pruning and |
7 | | - against the decoded array for the boundary fold), and §6 (zone-map aggregate push-down, both the |
8 | | - whole-zone and boundary-zone tiers) are implemented in `reader.compute`. Deferred: encoded-domain |
9 | | - kernel specialization (perf escalation — pushing the predicate into the ALP/FoR/Dict integer |
10 | | - domain without decoding), and the ergonomic façade (a columnar transducer — its own ADR). |
11 | | - `MapKernel` is unbuilt (no consumer yet). |
| 3 | +- **Status:** Accepted, implemented — with §1–§3 superseded in implementation (see the |
| 4 | + *Implementation note* below). Built in `reader.compute`: §4 (`Predicate`), §5 (`RowFilter` |
| 5 | + unified over `Predicate` — a `RowFilter.Column` binds a column to a shared public `Predicate`, |
| 6 | + the same predicate compiled against zone-map stats for pruning and against the decoded array for |
| 7 | + the boundary fold), and §6 (zone-map aggregate push-down, both the whole-zone and boundary-zone |
| 8 | + tiers). §1 (`Mask`) and §2/§3 (the `FilterKernel`/`MapKernel`/`ReduceKernel` interfaces and the |
| 9 | + mask-based no-materialize contract) were built and then **removed**: the shipped design is the |
| 10 | + fused single-pass kernels `Compute.filteredSum` / `filteredAggregate`, which fold filter and |
| 11 | + reduce in one scan with **no intermediate selection bitmap** — a stronger no-materialize |
| 12 | + guarantee than a `Mask` could give. Deferred to their own ADRs: encoded-domain kernel |
| 13 | + specialization (perf escalation — pushing the predicate into the ALP/FoR/Dict integer domain |
| 14 | + without decoding) and the ergonomic façade (a columnar transducer, ADR 0019). |
12 | 15 | - **Date:** 2026-06-15 |
13 | 16 | - **Deciders:** project maintainer |
14 | 17 | - **Supersedes:** — |
|
18 | 21 | [ADR 0010 — Lazy decode](0010-lazy-decode.md), |
19 | 22 | [ADR 0012 — Zero-copy layout decoding](0012-zero-copy-layout-decoding.md) |
20 | 23 |
|
| 24 | +## Implementation note (2026-07-01) |
| 25 | + |
| 26 | +The primitives shipped, but §1–§3 as drawn below did not survive the perf work. The `Mask` sealed |
| 27 | +type, the `FilterKernel` / `MapKernel` / `ReduceKernel` interfaces, and the mask-based |
| 28 | +no-materialize contract were implemented, benchmarked, and then removed. A materialized selection |
| 29 | +`Mask` is a positional bitmap the reduce must re-scan — strictly slower than fusing the filter and |
| 30 | +the reduce into one pass. The shipped surface is two fused kernels behind the minimal public |
| 31 | +`Compute` entry point, with everything else package-private: |
| 32 | + |
| 33 | +- `Compute.filteredSum(filterColumn, predicate, aggColumn)` — one filter column, one summed column. |
| 34 | +- `Compute.filteredAggregate(chunk, filter, aggColumn)` — an n-ary `AND` `RowFilter` and a |
| 35 | + `SUM` / `MIN` / `MAX` / non-null-count fold over the rows it selects. |
| 36 | + |
| 37 | +Both fold filter and reduce in a single scan with no intermediate bitmap, honoring §3's |
| 38 | +no-materialize intent more strictly than a `Mask` pipeline would; each is type-specialized into |
| 39 | +boxing-free long / double lanes with a generic boxing fallback. `MapKernel` was never built (no |
| 40 | +consumer). The `Predicate` (§4) and `RowFilter` unification (§5) vocabulary is unchanged and is what |
| 41 | +these kernels consume. The sections below are preserved as the original proposal; read §1–§3 as |
| 42 | +history, not as the built design. |
| 43 | + |
21 | 44 | ## Context |
22 | 45 |
|
23 | 46 | ADR 0010 establishes that the reader defers transform work until access |
|
0 commit comments