Repository navigation
refactor: Stage 2 outputs PhysicalASAPMemoCandidates; costs move to Stage 3 (#1047 P5c) - #1093
Merged
Merged
Conversation
Stage 2's output was spread over CandidateDependencyGraph, CandidateConfigurationInventory, CandidateOperatorTemplates and CandidateInventory in asap_types::stages, and carried zero cost placeholders. It is now one boundary type, PhysicalASAPMemoCandidates: operator nodes of candidates for memo groups (with every memo candidate a factored node can implement), physical candidates (operator node, timing, materialization, suppliers per input, may_produce_query_output, may_keep_across_evaluations_per_sole_reader_query), query roots, reader constraints and a private per-group index of implementation roots. generate_physical_asap_memo_candidates in asap-physical-asap-optimization wraps inventory, configurations and structural pruning. Stage 2 prices nothing: costs and resource budgets live in plan-selection's private DagOfPhysicalCandidatesWithCosts, which lower bounds build and the MILP, components and refinement read; the modeled-cost check moved to Stage 3. Plans are unchanged (corpus snapshots, retro-check harness). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Build the output-reference groups once in PhysicalASAPMemoCandidates::new instead of on every query_output_candidates / output_reference_count call. - One shared helper, asap_types::stages::output_references, flattens query roots into output references for Stage 2, the route and components. - Stage 3 DAG names follow #1047: InputSupplierCandidates, supplier_candidates_per_input, QueryOutputCandidates { candidates }. - PhysicalASAPMemoCandidates::group -> memo_group_of; document and debug_assert that an operator node's memo candidates share one group. - Rename may_keep_with_sole_reader to the may_keep_across_evaluations_per_sole_reader_query wording; update stale comments and error strings. - A component's catalog clones only the operator nodes it uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 of 13 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #1047 (step P5c) and #1054 (Stage 2 has one output type and carries no cost).
Why
After P5b (#1090), Stage 2's output was still spread over four types:
CandidateDependencyGraph,CandidateInventory,CandidateConfigurationInventoryandCandidateOperatorTemplates. Its candidates carriedlocal_costandresource_budgets, which Stage 3 filled in. #1047 decided that each stage boundary has one named type, and that Stage 2 does not price anything.What
The change is behavior-preserving: selected plans are unchanged (see Verification).
build_candidate_inventory_before+enumerate_candidate_configurations_before+prunecatalog::generate_physical_asap_memo_candidatesCandidateInventorycandidate + itsCandidateOperatorTemplatesentryOperatorNodeOfCandidateForMemoGroup, one per operator nodeCandidateConfiguration+ graph candidatePhysicalCandidate, one per timing, materialization and scope copysource_candidateoperator_nodeproducer_requirementssupplier_candidates_per_inputmay_keep_with_sole_readermay_keep_across_evaluations_per_sole_reader_querymemo_candidate_roots, returned next to the inventorycandidates_for_memo_groupon each operator nodegroup_candidates,graph.query_roots[r]implementation_roots(group),query_output_candidates(r)(same IDs, same order)local_cost,resource_budgets, and the cost check in Stage 2's reconstructionDagOfPhysicalCandidatesWithCosts(plan-selection), checked by Stage 3 before reconstructionDeleted:
CandidateInventory,CandidateConfigurationInventory,CandidateConfigurationandCandidateOperatorTemplates;node_local_costcallback, with itsCosterror;ConfigurationError::UnpricedResources.CandidateInventoryremains as a type private to the physical crate.How
Stage 2 (
physical-asap-optimization/src/catalog/):local_cost, which was always 0 in production;PhysicalASAPMemoCandidates;Stage 3 (
plan-selection):DagOfPhysicalCandidatesWithCostsfromPhysicalASAPMemoCandidatesonce per round, and lower bounds fill in its costs;PhysicalASAPMemoCandidatesper component, withnew, and clones only the operator nodes that component uses.Shared:
asap_types::stages::output_referencesflattens query roots into output references, replacing five copies.PruningMetricsmoved toasap_types::stagesaspruning_metrics, which stands in until P6 addspruned_candidates.Key code interfaces added / modified
crates/types/src/stages/physical/memo_candidates.rscrates/physical-asap-optimization/src/catalog/mod.rsUsage:
stage_pipeline --workload …runs each pane-width round as follows:LogicalASAPMemoCandidates.generate_physical_asap_memo_candidatesreturnsPhysicalASAPMemoCandidates.DagOfPhysicalCandidatesWithCostsfrom it, fills in costs with lower bounds, and searches with the MILP.(&PhysicalASAPMemoCandidates, selection).The selected plan is the same as before.
Major algorithm changes
None. One change in what you see: on a selection that is invalid in two ways at once, Stage 3's cost check now runs before the entry-count check, so the error message can differ.
Before / After
PhysicalASAPMemoCandidates, and keeps its costs in its own DAG.Verification
At
e3079a983(rebased on mainb1f001b6e):fmt and clippy:
cargo fmt --allandclippy --workspace --all-targets -D warningsare clean.Tests:
--lib: 336 passed.filtered_kll_states_cost_no_more_than_separate_plans,topk_reuse) pass alone.Corpus snapshots: pass. They cover only single-query exact plans, so plan equality was also checked directly.
Selected-plan comparison, with
stage_pipelineand accuracy guarantees enforced, compared strictly on all fields:Dependencies:
cargo tree -p asap-physical-asap-optimization --edges normal --depth 1lists asap-accuracy, asap-types, rmp-serde, serde, serde_json and thiserror.Independent review: no blocking findings. It verified:
operator_node;test-supportis enabled only in dev-dependencies.Its nits are fixed in the second commit: output references are built once, there is one flattening helper, the Stage 3 DAG fields are renamed,
memo_group_of, and stale names and comments are cleaned up.External impact: none outside this repo.
🤖 Generated with Claude Code