Repository navigation
planner-layering.md: the memo through the stages, and the memo to candidate DAGs algorithm #1007
Description
Problem, by example
Example workload: one query, evaluated every minute, with max_error 0.01 and failure_probability 0.001:
avg by (job) (quantile_over_time(0.5, data[5m]) / quantile_over_time(0.5, data[5m]) + quantile_over_time(0.9, data[5m]))
The memo the planner builds for it on main (0f7465c96), measured with LogicalMemo::from_roots, try_populate_pass1 and the expanded_memo test helper:
| Group | Logical sub-expression | Reads |
|---|---|---|
| G0 | Scan data |
– |
| G1 | TimeRange 5m |
G0 |
| G2 | per-series quantile 0.5 |
G1 |
| G3 | per-series quantile 0.5 (structurally equal to G2, but a separate group; see below) |
G1 |
| G4 | G2 / G3 |
G2, G3 |
| G5 | per-series quantile 0.9 |
G1 |
| G6 | G4 + G5 |
G4, G5 |
| G7 | avg by (job) |
G6 |
| After | Groups | Implementation candidates | Full candidate DAGs |
|---|---|---|---|
| Stage 0 | 8 | – | 1 |
| Stage 1, Pass 1 | 8 | 26 (G2, G3 and G5 have 7 each) | 343 = 7 × 7 × 7 |
| Pass 2 window composition + concrete state groups | 378 (360 are PaneChain shared-build groups) |
2614 (G2, G3 and G5 have 745 each: 13 Pass 1, 360 Panes, 372 SharedBuild) |
> 1,000,000 (a naive enumerator stopped there) |
G2 and G3 are separate groups because share_common_sub_dags (crates/types/src/ir/cse.rs) shares a non-ASAP node only when its schema has a provable unique key, and this per-series quantile's output schema has none.
A reader of docs/design_docs/proposals/planner-layering.md can't predict these tables. The section "The stages over a memo of sub-expressions" says what each stage decides over groups, but it is out of date:
- it names
crates/plan-selection/src/search/memo/,brute_force::memoandbrute_force::brute_force, which no longer exist; - it gives no worked example of a memo through the stages;
- it doesn't say how the memo maps back to the vector of candidate DAGs the stage table describes.
Proposal
Rewrite that section. Prose the author wrote elsewhere stays unchanged, and the section cites no PR numbers. It covers:
- Components:
LogicalMemoandMemoGroup(Stage 0 hash-consing, including when two equal nodes stay separate groups);CandidateMemo,ImplementationCandidateandCandidateOrigin(which rule adds which candidates).
- The example above through each step: groups, candidates and candidate-DAG counts per step, as the code produces them.
- Algorithm, memo to candidate DAGs:
MemoChoice,memo::enumerateandmemo::compose, and why the count is not a product over groups (shared groups, fused candidates, groups needed only under some choices). - Code interface: current paths and entry points.
Scope and acceptance
- Every type, function and path the section cites exists on
main. - The numbers in the example match the
stage_pipelinememo-section test. - Lands after docs(planner-layering): stage inputs and outputs, whole-workload candidates and memo #977 (stage inputs and outputs) and Memo: convert memo-group candidates into the vector of all candidate DAGs #1002.
Activity
docs(planner-layering): the memo through the stages, and memo to cand…
zzylol commentedon Oct 28, 2026
Corrected 2026-10-28: production numbers from the stage-pipeline document; earlier numbers came from a test helper without the series-identity column.
The example in this issue was measured with
asap_integration_tests::fixtures::lower_promql/expanded_memo. That lowering omits the PromQL series-identity column, so the per-series quantile had no unique key and the twoquantile_over_time(0.5, data[5m])stayed two groups (G2, G3). The production frontend adds$promql_series_identity, which gives the per-series output a unique key (series identity, timestamp), so they share one group. Production numbers, fromtools/dag-viewer/examples/memo-ratio-of-quantiles.json(mainatd728d05c):Scan dataTimeRange 5mquantile 0.5(both occurrences)G2 / G2quantile 0.9G3 + G4avg by (job)budget_share1)Panes)PaneChainshared-build groups)Panes, 345SharedBuild)For this issue: the design doc's memo example now uses these production numbers.