Repository navigation
feat: InstallablePlan describes every stored summary through its SummaryCoverage (#781) - #787
Merged
Merged
Conversation
…age (#781) - SummaryCoverage::definition_id: a 128-bit FNV-1a hash, in hex, of the definition sub-DAG's operators, output kinds and schemas, children first, without timing, guarantee or materialization. Equal definitions (the equality a merge requires) get equal ids on any node. - SelectionBox, ColumnIdentity and Constraint serialize: columns as a list of {column, constraint}, bounds as {"included"|"excluded": v} or "unbounded". - PhysicalASAPDAG::operator_nodes: every node of a DAG as IR by id, the rebuild query_time_reference already used, so a plan file's node coverage can be derived. Tests: equal ids across selections and timings, different ids for other computations, six 10-minute panes of an hour share one id with distinct time selections, JSON round trip.
StoredOutput no longer requires a pane of raw samples. Each stored output now gives: - coverage: its definition id and selection (SummaryCoverage), a merge's being the union of its inputs' selections under their definition, and a summary built from one stored output with no selection of its own (a rollup to a coarser grouping, or across series) taking that input's selection under a definition of its own; - inputs: the raw-sample windows and the stored outputs (by node id) its build reads; - built_at and retention_ms as before. An output built from stored outputs is kept for how far back its data reaches plus its readers' longest range-evaluation span; each stored input is kept as long as the outputs built from it need it. plan_installable lists every stored node in dependency order and refuses only what a runtime cannot build: a stored node that reads a source outside a raw-sample window, has no summary coverage, or that the executor does not compile with its inputs bound. The `pane` field is removed: it is the one raw-sample window of a pane's inputs, and its time is the coverage's selection. The module doc says how a runtime builds an output from stored inputs. Tests: a rollup from finer stored sums, a maximum across series from stored per-series maxima and a kept sliding-window merge of stored panes, each listed with its inputs, coverage, phase and retention and built in order from stored inputs to the query-time reference's answers; existing pane plans keep their windows, order and retention.
This was referenced Oct 21, 2026
GordonYuanyc
added a commit
that referenced
this pull request
Oct 21, 2026
Planner main fails clippy (-D warnings) and one runtime_install test since #787, #789, #795 and the joint search commit: - summary_coverage.rs: a Window alias for the relative time window (type_complexity). - workload_candidates.rs: an array instead of vec! (useless_vec). - query_candidates.rs: OperatorNode::reachable instead of a closure. - stage1_to_stage3.rs: allow too_many_arguments on search_stage2_and_stage3, as lib.rs already does once. - joint_search_equivalence.rs: struct initializer for the settings, and slice::from_ref instead of a clone. - runtime_install.rs: the merged-pane DDSketch candidate of the p99 avg workload is now P3-m1 (was P5-m1); every other assertion of that test passes unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zzylol
pushed a commit
that referenced
this pull request
Oct 21, 2026
refactor: follow asap_sketchlib's UnivMon, Hydra and HLL renames UnivMon fields rows/cols/layers/total_weight/layer_heaps, new/clear/ update_weighted/estimate_*, OwnedDataInput, UNIVMON_MAX_LAYERS; Hydra rows/cols and HydraCounter::CountMinSketch; HLL update_with_hash. refactor!: HLL, KLL, DDSketch, Count-Min and KMV kernels on native asap_sketchlib types The portable HllSketch, KllSketch, DdSketch and CountMinSketch are gone from asap_sketchlib. HLL is a classic HyperLogLogImpl at each precision 4..=18 (register types from impl_hll_registers!); KLL is Kll::with_k; DDSketch the native DdSketch (get_value_at_quantile, get_count); plain Count-Min a regular-path CountMinF64 that adds every weight, zero and negative ones included; KMV the native Kmv. Memory charges come from Kll::memory_bytes, Kmv::memory_bytes and CountMinSketch::memory_bytes. The DDSketch ratio tests interpolate PromQL quantiles from the sketch's order statistics. refactor!: weighted frequency on asap_sketchlib's f64 Count-Min and Count Sketch asap_sketchlib drops WeightedFrequency. The Planner kernel keeps its API over CountMinSketchWithHeap / CountSketchWithHeap (capacity > 0) or a plain CountMinSketch / CountSketch (capacity 0), all Vector2D<f64> on the regular path. An identity tuple is one TupleKey, hashed and retained as bytes. Planner checks what sketchlib does not: finite weights (and nonnegative for Count-Min), finite Float64 identities, an odd Count Sketch depth, and a total weight magnitude within f64. Top-k rows are the heap's keys at their current estimate, descending, ties by key bytes. refactor!: HydraKLL on asap_sketchlib's Hydra with KLL cells (#644) HydraKllSketch is gone from asap_sketchlib. The kernel is a one-column Hydra over HydraCounter::Kll, read by Hydra's median of the cells' KLL quantiles, and charged the cells' Kll::memory_bytes. refactor: box the weighted frequency state held as a template Its heap makes it far larger than the other group-state kinds. test: fixtures that still exercise native KLL memory and DDSketch quantiles Kll allocates its item buffer as items arrive, so each stored-pane state takes 1,100 samples to hold its full buffer (about 11 kB) again; with one sample the merge fit the 4 MiB limit. DdSketch reads its minimum and maximum exactly, so the cross-zero ratio fixture interpolates interior order statistics: [-2, -1, 1.011, 2] instead of [-1, 1.011]. chore!: pin asap_sketchlib to main (de15d66) asap_sketchlib main, with ProjectASAP/asap_sketchlib#242 merged. UnivMon builds any row count its 128-bit key hash covers, so the UnivMon shape tests probe that budget instead of a 20-row limit. Merge remote-tracking branch 'origin/main' into chore/asap-sketchlib-main fix: cap UnivMon at the 20 rows its ASAPv1 state encodes sketchlib main's UnivMon::check_shape accepts any row count within the 128-bit key hash, but its ASAPv1 encoder still refuses more than MATRIX_MAX_ROWS rows. Keep the executor's builds and the Planner's hash_independent at 20 rows, as on the old pin, so every UnivMon state the executor builds can be stored. fix: count the KLL and weighted frequency structs once in memory charges Kll::memory_bytes and the heap sketches' memory_bytes already include their own struct; adding size_of::<Self>() on top counted it twice. chore: pin asap_sketchlib to release 0.4.0 (eb04e7f) eb04e7f is the 0.4.0 release commit on top of de15d66; the library code is the same, only the version, CHANGELOG and README change. Merge remote-tracking branch 'origin/main' into chore/asap-sketchlib-main # Conflicts: # crates/plan-selection/src/lib.rs fix: clippy on main's new code and the renumbered P99 pane candidate Planner main fails clippy (-D warnings) and one runtime_install test since #787, #789, #795 and the joint search commit: - summary_coverage.rs: a Window alias for the relative time window (type_complexity). - workload_candidates.rs: an array instead of vec! (useless_vec). - query_candidates.rs: OperatorNode::reachable instead of a closure. - stage1_to_stage3.rs: allow too_many_arguments on search_stage2_and_stage3, as lib.rs already does once. - joint_search_equivalence.rs: struct initializer for the settings, and slice::from_ref instead of a clone. - runtime_install.rs: the merged-pane DDSketch candidate of the p99 avg workload is now P3-m1 (was P5-m1); every other assertion of that test passes unchanged.
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.
Why
A runtime's summary store should hold every summary the plan stores.
InstallablePlancould describe only one kind: a node built directly from one pane of raw samples (StoredOutput.pane).plan_installablerefused anything else withStoredOutputWithoutPane. For example, a sliding-window merge of stored panes kept across evaluations failed withInstallable(StoredOutputWithoutPane { node_id: 15 }). So a runtime could store only panes, and every other summary the plan stores was refused at install time.What
StoredOutputsays what the stored summary is, what its build reads, when it is built, and how long it is kept:coverageis the IR'sSummaryCoverage: a stabledefinition_idand theselection(value sets, value ranges, and time relative to the evaluation time).inputsare the raw-sample windows and the stored outputs (by node id) it reads.built_atandretention_msare as before.plan_installablelists every stored node (MatAtIngestionorMatAtQueryKeptAcrossEvaluations) in dependency order. It refuses only what a runtime cannot build: a stored node that reads a source outside a raw-sample window, a stored node with no summary coverage, and one the executor does not compile with its inputs bound.paneis dropped. It was the single raw-sample window of a pane'sinputs, and its time is the time part of the selection. Its consumers are this repo's tests, which are migrated here, and ASAPQuery-backend, which is migrating to the general form.installablemodule doc) say how a runtime builds an output from stored inputs.How
Coverage.
SummaryCoverage::derive.SummaryMergerules.definition_id. A 128-bit FNV-1a hash of the definition's operators, output kinds and schemas, children first. It ignorestiming,guaranteeandmaterialization, so it agrees with the equality a merge requires. A summary store can key instances by (definition id, concrete selection).Inputs. Walking down from a stored node, each stored node and each raw-sample
TimeRangeit reaches is an input. AScanreached without aTimeRangeis refused. Stored outputs are ordered children first, so a pane-only plan keeps its node order.Executability. For each stored output, the executor's own
compileruns with its inputs bound as sources, the way a runtime runs it. A failure is refused with the executor's reason.Retention.
end_offset_ms + width_ms). An output built from stored outputs adds its readers' longest range-evaluation span.validaterefuses an output kept for less than its data reaches.Shapes Stage 3 does not select today. With the built-in models, none of the three shapes in the issue is selected:
MatAtQuery);SummaryMergeas a materialization candidate.The tests force these shapes through
UserInput::pass. A test pass runs Stages 1 to 3, re-times the selected plan with the chosen nodes stored, and splits nodes shared across timings as Stage 2 does. It then goes throughplan_installableunchanged.Key code interfaces added / modified
crates/planner/src/installable.rscrates/types/src/ir/properties/summary_coverage.rscrates/types/src/ir/physical_export.rsUsage (the test
a_kept_sliding_window_merge_is_listed_and_built):Before this PR
StoredOutputWithoutPane, for example the kept merge above.After this PR
inputs.raw_sample_windows[0]),built_atandretention_ms. The new fields are added andpaneis gone.Verification
Tests written first.
main.plan_installableof the kept-merge plan failed onmainwithStoredOutputWithoutPane { node_id: 15 }.planner/tests/runtime_install.rs. Each test checks inputs, coverage, phase and retention, then builds every output in the listed order from stored inputs with the executor. The answers equalquery_time_reference.a_rollup_from_finer_stored_sums_is_listed_and_built:sum by (job)from storedsum by (job, instance), both at ingestion. The selection is(−60s, 0]for both, the definitions differ, and 2 builds are needed.a_summary_across_series_from_per_series_summaries_is_listed_and_built:max by (job)from stored per-series maxima.a_kept_sliding_window_merge_is_listed_and_built: as in the usage above. A second evaluation one minute later builds only the newest pane and the new merge.panes_of_an_hour_share_one_definition_with_distinct_times: the six 10-minute panes ofquantile_over_time(0.99, latency_ms[60m])share one definition id. Their time selections are(−(i+1)·10m, −i·10m]and their windows are unchanged.per_sample_updater,columnar_batchesandintegration-tests/runtime_handoff.types/tests/summary_coverage.rs.equal_definitions_get_equal_ids: equal across selections and timings, different for another column, family or source.panes_of_an_hour_share_one_definition_with_distinct_times: the same property, plus their merge.selections_round_trip_through_json.Commands.
cargo test --workspace --lockedat the head: exit 0, 150 test binaries, 0 failures. Following the current speed-first policy,fmtandclippywere not run.Limitations.
SummaryCoveragerules:TimeRangeand its label matchers stay in the definition, with no time in the selection. Such a state's concrete identity also needs the evaluation time; the test harness adds it to the key.SummaryMergeas a materialization candidate, and Stage 3 does not select the forced rollup shapes under the built-in prices. This PR makes them installable; making Stage 2 and Stage 3 choose them is separate work.Closes #781