[Refactor] Pane-width rounds without cross-stage calls: rerun Pass 2 per round, or pass an incremental Pass 2 state #1048
Description
Example
Workload tools/dag-viewer/memo-examples/promql/ratio-of-quantiles-5m.json: one query, evaluated every minute, with max_error 0.01:
avg by (job) (quantile_over_time(0.5, data[5m]) / quantile_over_time(0.5, data[5m]) + quantile_over_time(0.9, data[5m]))
Over the complete pane-width domain, Pass 2 gives this one query 336 PaneChain shared-build groups (production numbers from #1010). That is too many to generate before a first plan exists. So the search (candidate_connection_search in crates/plan-selection/src/search/route.rs) runs in rounds:
- Seed round.
PaneWidthDomain::SeedGrids, budgetmin(¼ of the remaining time, 5 s). - Wider rounds.
PaneWidthFrontier::next_domainyieldsExpanding { max_parts }domains, thenComplete. Each non-complete round gets at most 5 s and 16 evaluations. - Merge. The best validated plan across rounds is kept (
merge_validated_rounds).
Between rounds, Pass 2 is incremental:
DomainProgress.local_memokeeps the memo from before state-group expansion.extend_local_window_composition(&mut memo, entries, previous_domain, domain, deadline)adds only the widths new in this round.expand_concrete_summary_state_groups_beforethen runs on a clone, because expansion can run only once on a memo.
Rounds run only when the workload has a pane window, the search is not exhaustive and does not keep every candidate, and the budget allows it. stage_pipeline with keep_every_candidate therefore always runs one Complete round.
The decision
#1047 moves the rounds into the asap-planner facade (Pass 2 → Stage 2 → Stage 3 per round) and forbids calls across stages. Pass 2 then needs one of:
- A. Stateless (proposed first step).
generate_logical_asap_memo_candidates(&pass1, entries, pane_widths, deadline)regenerates Pass 2 from scratch each round. This is simple, and no hidden state crosses stages. It repeats the window composition for widths earlier rounds already produced. - B. Incremental handle. Pass 2 returns its output plus an opaque
Pass2State(today'slocal_memo+previous_domain). The facade passes the state back into the next round without reading it. This saves the repeated generation, but it adds a type that lives across rounds.
Proposal: implement A, measure it, and switch to B only if the measurement requires it.
Acceptance
Measure on the same host with a release stage_pipeline, with rounds enabled (no --exhaustive, default keep_every_candidate = false), on:
promql/ratio-of-quantiles-5m.json- the five
promql/rangeheavy-*.json - the random mixed workloads
Compare A against main:
- the selected plan and its cost
- the number of rounds completed within the budget
- Pass 2 time per round
- total planning time
- peak RSS
A is kept if the selected plans are identical and the total planning time and peak RSS are within the #1047 threshold (10%). Otherwise implement B and measure again.
Related
- Parent: [Refactor] One named type per stage boundary: PerComputationLogicalMemoCandidates → LogicalASAPMemoCandidates → PhysicalASAPMemoCandidates #1047 (stage-boundary types; no calls across stages)
- Reorganize by stage: one memo-based Pass 2, Stage 1 finishes the memo, deployment inputs split by stage, asap-planner as the only entry point #958 (reorganize by stage)
- Stage 1 Pass 2 review: ASAP-aware CSE rules over memo groups and summary-state groups #1013 (Pass 2 review)
- Tracking: plan every whole evaluation workload within 3 minutes (exact pruning, memo-group search) #879 (plan whole workloads within minutes)
Activity