Conversation
This was referenced Aug 23, 2026
Closed
zzylol
force-pushed
the
feat/replacement-strategy-251
branch
from
August 23, 2026 19:59
ca60c0c to
66c772d
Compare
…rrent tip This branch had been forked at the very first draft of #251 (boundary::implementation_for_with, a ForceSketchKind CostModel-wrapping hack to steer bind::implement_tree_with) and never rebased — completely missing #259's subsequent history: the boundary.rs -> implementation.rs rename, the "make binding literally a selector over ReplacementStrategy" refactor, and this session's deletion of bind::implement_tree/implement_tree_with. It would not compile against the current tip of feat/replacement-strategy-251. Rebuilt fresh: reset this branch onto the current #259 tip, then reapplied only the genuinely new content search.rs adds on top — nothing here re-implements replacement.rs/bind.rs, which now come from #259 itself. - search.rs's two implement_tree_with call sites replaced with the established take-the-first-candidate pattern (SketchFamilyStrategy::replacements(...).into_iter().next(), falling back to bind::logical) — the same helper shape bind.rs's own tests and every external caller of this crate now use. - structural_hash's signature grew a `cache: &mut HashCache` parameter since this branch forked (issue #244, CSE stage 3, landed on main in the meantime) — is_duplicate_rewrite now threads a fresh HashCache through its one pairwise comparison. - Made HashCache pub (was pub(crate)) alongside structural_hash, for search.rs's cross-crate reuse — same rationale already documented for structural_hash itself. - lib.rs: added the `search` module doc bullet, `pub mod search;`, and its public re-exports; fixed two stale `boundary::` doc references in search.rs itself. Verified: cargo build --workspace --all-targets, cargo test --workspace (0 failures, including all 12 search:: tests), cargo fmt --all -- --check, cargo clippy --workspace --all-targets --all-features -- -D warnings — all clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
zzylol
force-pushed
the
feat/cascades-search-252
branch
from
August 24, 2026 14:03
9d22b7e to
7b14b4b
Compare
zzylol
added a commit
that referenced
this pull request
Aug 24, 2026
…licability.rs "Site" was an informal synonym introduced when this module's docs were written — every occurrence names the exact same thing the type system already calls TargetSubDAG (or, once discovered, a MemoGroup's own `target`). Replaced every free-standing "site"/"a site's..." with TargetSubDAG (or "the TargetSubDAG" as a phrase) throughout the module doc and the OptimizationKind/collect_locations/test doc comments, so the prose names the real type instead of a parallel, undefined term. Left two references untouched: `crate::search::discover_sites` (a real, unrenamed function name in search.rs) and the quoted section title "Where `for site in plan.bindable_sites()` comes from" (a verbatim quote of search.rs's own doc heading) — both are accurate references to search.rs's own content, which this PR doesn't touch. Also fixed a handful of stale `boundary::`-module doc links found while in here (the module was renamed to `implementation` well before this branch's fork point — same staleness class as PR #263/#262/#261/ #260, just not load-bearing for compilation since these were doc-only intra-doc links). Verified: cargo build --workspace --all-targets, cargo test --workspace (0 failures), cargo fmt --all -- --check, cargo clippy --workspace --all-targets --all-features -- -D warnings — all clean.
zzylol
added a commit
that referenced
this pull request
Aug 24, 2026
…'s current tip #263 (feat/cascades-search-252) was just rewritten (force-pushed) as part of syncing every #33 sub-issue PR to #259's current tip. This branch, stacked on #263, was still built on #263's old (pre-rewrite) history, which made the two branches diverge and GitHub start reporting this PR CONFLICTING against its base. Rebuilt fresh: reset onto #263's current tip, then reapplied applicability.rs (already updated per this PR's own review-comment fixes: "site" -> TargetSubDAG throughout, stale boundary:: doc links fixed) verbatim, since it depends only on crate::search/crate::replacement, both stable and unchanged in shape across the rewrite. Wired it into lib.rs (pub mod applicability;, its Status bullet, and its exports), and picked up two small search.rs doc improvements this PR had made (replacing "a hypothetical applicability::..." with real references, now that this module exists) that were otherwise lost. The design doc's old "## Applicability reporting" section this PR originally added lived at docs/asap_aware_mapping.md, a path deleted by the docs reorg (#265) that landed on main in the meantime; the design doc's current location (docs/design_docs/asap_aware_mapping.md) already carries its own "# Applicability Reporting" section, written independently and already consistent with this PR's own terminology fix (uses "Target Sub-DAG" throughout, no "site"). Left it untouched rather than reintroducing now-orphaned content. Verified: cargo build --workspace --all-targets, cargo test --workspace (0 failures, including all 11 applicability:: tests), cargo fmt --all -- --check, cargo clippy --workspace --all-targets --all-features -- -D warnings — all clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
zzylol
added a commit
that referenced
this pull request
Aug 24, 2026
…d CostModel::estimate_cost ## Why PR #263 (feat/cascades-search-252) built a Cascades/Volcano-style MEMO search engine (search.rs: PlanSpace/MemoGroup/RankedGroup/ search_workload/search_workload_with) but was paused for lacking a concrete use case. That use case now exists: replacement's "always return every candidate" principle should hold at whole-workload granularity too, and a flat Vec of fully-materialized candidate DAGs is combinatorially infeasible there (N independently-choosable sites -> 2^N plans) -- search.rs already built the right MEMO structure for this. Its base predates the implementation.rs->replacement.rs merge and the Logical->KeepPreAsap rename, so its content is manually re-integrated here rather than merged/cherry-picked. ## What - bind.rs shrinks: select_and_bind and keep_pre_asap (both single-target-scoped helpers with no workload-level state) move into replacement.rs, next to construct_summary/SketchFamilyStrategy which are their only real callers. bind.rs keeps only ImplementError, implement_workload/implement_workload_with (unchanged bodies -- these own genuine cross-root Rc-identity memoization state a per-target module has no business holding), and its own tests. select_and_bind is pub(crate) (bind.rs is its only other caller). keep_pre_asap stays pub and is re-exported from bind.rs (`pub use crate::replacement::keep_pre_asap;`) so `asap_aware_mapping::bind::keep_pre_asap` keeps resolving for existing external callers (devtools, frontend-promql tests, integration-tests) -- pub(crate) can't be re-exported wider than its own crate, so this was the only option that doesn't break the build. - search.rs's content (MAX_SEARCH_ITERATIONS, MemoGroup, PlanSpace, RankedGroup, is_duplicate_rewrite/is_duplicate_summary, rank_group, cse_preference, default_strategies[_with], search_workload[_with], site discovery) moves directly into replacement.rs -- no `mod search`, flattened into the same namespace as TargetSubDAG/ Replacement/ReplacementStrategy/SketchFamilyStrategy/ SharedSubtreeStrategy. crate::bind::bindable_intent and crate::bind::logical (renamed keep_pre_asap on this branch's tip) become local references; search.rs's own bind_one helper is unified with select_and_bind (`select_and_bind(target, cost_model).ok()`) since both did near-identical take-first-or-fall-back-to-keep_pre_asap work. The doc-link to `implementation::implementations_for_with` (module-private, per the earlier implementation.rs merge) drops its `[...]` brackets, matching cost_model.rs's existing style for doc-links to private items. asap_types::pre_asap::cse::structural_hash/HashCache go from pub(crate) to pub -- search.rs's own is_duplicate_rewrite doc already says "made pub for exactly this reuse", assuming a change that never actually landed on this branch's base; landing it now is what makes the merged code compile. search.rs's own #[cfg(test)] mod tests merges into replacement.rs's existing test module: its metric_scan/agg fixture helpers and `Reduction`/`Schema`/`AggIntent`/DefaultCostModel imports were identical (or made redundant by `use super::*`) to what the existing module already had, so those are dropped and the merged tests reuse the existing helpers directly. - CostModel::estimate_cost(&self, candidate: &ReplacementSubDAG, target: &TargetSubDAG<'_>) -> f64: a new trait method exposing an actual numeric cost per candidate (today PlanSpace::cost_sorted only exposes relative order), covering both Replacement::Summary (SketchFamilyStrategy) and Replacement::Rewrite (SharedSubtreeStrategy) shapes. Default body returns f64::NAN, documented as an explicit "not a real cost model" placeholder -- not a breaking change for existing CostModel implementors. DefaultCostModel overrides it, reusing (not duplicating) cse_recompute_cost/ cse_shared_maintenance_cost -- the same arithmetic already backing cse_share_decision: a Summary candidate costs cse_recompute_cost(target) + cse_shared_maintenance_cost(candidate's bound family); a Rewrite candidate costs cse_shared_maintenance_cost (if it's the "share" candidate, i.e. Rc::ptr_eq to target) or cse_recompute_cost * consumer_count (if it's "recompute independently"), recovering a representative bound SummaryNode via select_and_bind when needed. RankedGroup gains a `costs: Vec<f64>` field, aligned index-for-index with `candidates`, populated by PlanSpace::cost_sorted by calling estimate_cost per already-ranked candidate -- purely additive, does not change cost_sorted's existing ranking behavior/tests. - lib.rs: no `pub mod search`; PlanSpace/MemoGroup/RankedGroup/ search_workload/search_workload_with/default_strategies[_with]/ MAX_SEARCH_ITERATIONS fold into the existing `pub use replacement::{ ... }` block. `## Status`/`## Terminology` rewritten: the `replacement` bullet now covers decide+construct+search-across-a- workload as one module's job (the old "no search/ranking-across-a- whole-plan logic lives here" language is gone); a new Terminology row covers workload-wide search, reusing search.rs's own MEMO-groups framing; the `bind` bullet explains the shrink and why implement_workload/implement_workload_with still deserve their own module (genuine cross-root memoization state). - Developer guide: bind::keep_pre_asap/bind::select_and_bind references become replacement::keep_pre_asap/replacement:: select_and_bind; the "not yet the whole-plan Cascades/Volcano-style search" paragraph is rewritten to describe search_workload/ PlanSpace as implemented; the extension map gains rows for search_workload, PlanSpace::cost_sorted, and CostModel::estimate_cost. docs/design_docs/asap_aware_mapping.md was checked and left as-is -- it's a timeless design document with no "not yet implemented" language to update, and no literal "Pseudocode for Replacement Plan Searching" heading to annotate. ## Output $ cargo build --workspace --all-targets && cargo test --workspace \ && cargo fmt --all -- --check \ && cargo clippy --workspace --all-targets --all-features -- -D warnings (all clean; asap-aware-mapping: 69 passed, 0 failed) PR #263 (feat/cascades-search-252) is superseded by this merge -- its content now lives inside this branch. Left open for the user to close. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
zzylol
added a commit
that referenced
this pull request
Aug 24, 2026
…nSpace (#257, part of #33) Absorbs PR #264 (feat/applicability-view-257) into this branch, re-derived against the current tip rather than merged/rebased/cherry-picked (#264's base predates the SketchFamilyStrategy->SketchAlgorithmStrategy rename, the search.rs->replacement.rs merge, and the "site"->"target"/TargetSubDAG rename). Replaces the deleted PR #247 rule-based traversal with a pure view over replacement::PlanSpace: a TargetSubDAG is applicability-worthy exactly when its candidate list contains something beyond the trivial, no-op realization. - OptimizationKind::SketchApproximation — the candidate list contains a Replacement::Summary that realizes SummaryFamilyType::Sketch(..). - OptimizationKind::CommonSubexpressionReuse — consumer_count >= 2 and the candidate list contains SharedSubtreeStrategy's "build once and share" candidate. Each finding's `reason` is the matching candidate's own ReplacementSubDAG::rationale verbatim — no new prose. No new applicability-specific extension-point trait: a new finding needs a new impl ReplacementStrategy wired into default_strategies/default_strategies_with regardless, since that's the only way a candidate reaches PlanSpace at all. Kept as its own module (crates/asap-aware-mapping/src/applicability.rs, `pub mod applicability;` in lib.rs) rather than flattened into replacement.rs: unlike implementation.rs/search.rs, this is a reporting/presentation transformation (internal PlanSpace -> external ApplicabilityFinding shape for a downstream DAG-visualization consumer), a genuinely different kind of concern from generating or ranking candidates. Also fixes now-stale cross-references in replacement.rs that pointed at the deleted PR #247 ApplicabilityRule/SharedSubexpressionRule/register_site traversal, and a stale reference in the developer guide (section 4.2) to the same deleted trait. Adds an "Applicability reporting" section (§19) and an extension-map row to docs/developer_docs/ASAP-aware-mapping-developer-guide.md; docs/design_docs/asap_aware_mapping.md already carries a conceptual "Applicability Reporting" section and, matching this session's convention of keeping that document implementation-agnostic, is left as-is. cargo build --workspace --all-targets, cargo test --workspace, cargo fmt --all -- --check, and cargo clippy --workspace --all-targets --all-features -- -D warnings all pass clean. PR #264 (feat/applicability-view-257) and PR #263 (feat/cascades-search-252) are both now superseded by this branch; flagged for the user to close. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
Author
|
Superseded — its content (PlanSpace/MemoGroup/search_workload) was folded directly into #259 (feat/replacement-strategy-251) rather than staying a separate stacked PR. |
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.
Closes #252. Part of #33. Stacked on #259 (issue #251) — do not merge before that one.
Why
ReplacementStrategy(#251) lets different rewrite strategies propose alternative subtrees at a given site, but nothing actually searched that space: no workload-wide discovery of sites, no deduplication of candidates, no way to converge on and pick a winner.Separately, #237 deliberately chose a narrow, single-axis cost comparison (share vs. recompute one CSE'd subtree) instead of building real search infrastructure, because at the time there was only one decision to make. It explicitly flagged that this stops being enough once multiple interacting axes — sketch family choice, CSE sharing, future rewrite strategies — need to be considered together. This PR is that follow-up: the actual search engine, previously only sketched as pseudocode in
docs/asap_aware_mapping.md.What
Adds
crates/asap-aware-mapping/src/search.rs, the fixpoint search engine overReplacementStrategy, with public entry points:search_workload/search_workload_withdefault_strategies/default_strategies_withPlanSpace,MemoGroup,RankedGroupThese are the entry points issue #257 depends on.
Also makes two existing helpers reusable instead of duplicating them:
structural_hash(cse.rs) andbindable_intent(replacement.rs).How (core algorithm)
Memo structure, not flat plans. The search space is a Cascades/Volcano-style memo: each distinct replaceable subtree (identified by
Rcpointer identity) becomes oneMemoGroupholding every alternative replacement discovered for it. A candidate is never materialized as a standalone full plan — two candidates that differ at only one site share every other node by construction.Workload-wide site discovery. After running the existing CSE pass once,
discover_siteswalks every root's DAG to find every distinct site and its real consumer count — something asap-aware-mapping: generalize summary/CSE selection into a ReplacementStrategy trait with multiple candidates #251 explicitly left out of scope.Fixpoint loop. Each site is asked exactly once per registered strategy. A round can only add to the next round's frontier via a rewrite candidate's own children exposing genuinely new structure — never by re-asking a processed site. Both current strategies (
SketchFamilyStrategy,SharedSubtreeStrategy) are idempotent in this sense, so real workloads converge in one round regardless of size. A documentedMAX_SEARCH_ITERATIONScap panics with a clear message if a future strategy fails to converge (covered by a dedicated test).Deduplication reuses
cse.rs's own rule:structural_hashis a cheap filter,PartialEqis the actual duplicate decision — never the reverse. One explicit exception:SharedSubtreeStrategy's two candidates (share vs. recompute) are value-equal but must never be deduped against each other, since they're a genuinely distinct choice.Final ranking reuses the existing
CostModel(cse_share_decision,rank_candidates) rather than inventing a new comparison — keeping CSE: decide rule-based vs. cost-based framework for whether to actually share a detected common subexpression #237's decision and this search's ranking step a single source of truth instead of two drifting implementations.Checks
cargo build --workspace --all-targets,cargo test --workspace,cargo fmt --all -- --check, andcargo clippy --workspace --all-targets --all-features -- -D warningsall pass clean.🤖 Generated with Claude Code