Repository navigation
feat(precompute): per-sample columnar ingestion and columnar raw-sample windows - #830
Merged
Merged
Conversation
zzylol
force-pushed
the
feat/concurrent-engine
branch
from
October 20, 2026 23:52
1b5d7a9 to
a70c238
Compare
zzylol
force-pushed
the
feat/per-sample-ingestion
branch
from
October 21, 2026 00:08
1eeac23 to
d68efef
Compare
zzylol
changed the base branch from
feat/concurrent-engine
to
feat/watermark-barrier
October 21, 2026 00:08
zzylol
force-pushed
the
feat/watermark-barrier
branch
from
October 21, 2026 00:10
defe86d to
4987a39
Compare
zzylol
force-pushed
the
feat/watermark-barrier
branch
from
October 21, 2026 00:17
4987a39 to
0a5c014
Compare
…windows A stored output whose build is Scan -> TimeShift* -> TimeRange(pane) -> SummaryAgg over per-series groups is built per sample: each sample updates its series' summary state in the open pane with the executor's StateColumnUpdater, and closing the pane seals the states into one batch built with Batch::try_from_columns, stored in the SDS. Other shapes keep the plan's build over the pane's samples. Raw-sample windows become input batches column by column from cached per-series cells, without a Sample or row per sample, for query-time windows, QueryRun builds and the fallback build. Rows are read only to encode the answer. The plan is compiled once, on the installing thread.
zzylol
force-pushed
the
feat/per-sample-ingestion
branch
from
October 21, 2026 00:21
d68efef to
41ccfbe
Compare
zzylol
marked this pull request as ready for review
October 21, 2026 00:22
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.
Stack: main → this PR → series interning → no-forward mode. This PR merges the old #830 (per-sample ingestion) and #832 (columnar engine). It is built directly on main; #829 (concurrency) is deferred.
Why
Each pane build buffered every raw sample, turned each one into an executor
Samplewith an owned copy of its label map, then into a row ofValues, and built the summary state from those rows. Query-time raw-sample windows andQueryRunbuilds took the same path. ASAPPlanner main (pinnedecea897f) runs its operators on Arrow batches and exposesStateColumnUpdater(the per-sample summary state update the batchSummaryAggruns) andBatch::try_from_columns, so a runtime can build summary states per sample and install them as a stored pane without rows.What
Scan → TimeShift* → TimeRange(pane) → SummaryAgg, with per-series groups (the group columns include the series identity), is built per sample:Scan's label matchers (the executor'sRawSampleSelector) and the series' text cells, cached.StateColumnUpdater::updateon the open pane's summary state for that series, in arrival order. Stale markers are skipped, as the selector drops them.StateColumnUpdater::seal), and the pane is one batch built withBatch::try_from_columns(group texts, the pane's timestamp, the state column), stored in the SDS.TimeRangeand theSummaryAgg, matchers on value or time, or groups that are not series.series.rs). ARawSampleWindow's input batch is built column by column from the samples' times and values and each series' cached cells, with the selector's semantics: window bounds, latest sample per series for an instant selector, stale markers never rows. Used for query-time windows,QueryRunbuilds and the fallback build. NoSampleand no row is made per sample.Pane(the build's batches), bound to a query root throughOperator::sourcewithout copying.Batch::to_rowsis called only inresult_samples, which encodes the Prometheus JSON answer.Batch::try_new(rows to a batch) is no longer used.Sendnow). With one engine thread there is nothing to share throughArcyet; feat(data-plane): sharded ingestion workers, a query thread pool and a shared SDS #829 does that when it lands.How
PerSampleSpec(one per definition) reads theSummaryAggpayload for the value, time and group columns, as the executor's lowering does. It finds the output timestamp's offset from the pane end by running the plan's build once over one row.OpenPanesnumbers the series and holds oneStateColumnUpdaterper open pane. A pane's rows are the series that took a sample, in group-key order, as the batch build emits them.panes_failed, as a failed batch build was before.Usage
No new flags. With the examples' plans without raw data, the data plane logs
pane build per_sample=truefor each ingestion-time stored output at startup, and/api/v1/status/asapcounts are unchanged in meaning.Before this PR
Per pane: one
Sample(owned label map) and one row per raw sample, grouped into states by the executor's row path, and the result converted from rows back into a batch withBatch::try_new. Query-time raw-sample windows took the sameSamplepath.After this PR
Per raw sample: one cached-series lookup and one in-place summary state update. Per pane: one
try_from_columns. Rows are read only to encode the answer.Verification
cargo test --workspace --lockedpasses (fmt and clippy not run for this draft; the benefit harness was not rerun). Existing tests are unchanged except that the SDS holdsPane(SummaryStore<Pane>inquery_run.rs). New:per_sample::per_sample_panes_equal_the_batch_build: for Example 1 (counter rate and sum, 10 s panes), Example 3b (KLL, 1 min) and Example 4b (KLL, 10 min) without raw data, every pane built per sample equals the plan's own build of the same samples (Precompute::batch), row by row, with the same counters. Exact summary states are compared by serialized bytes, KLL by its quantiles at every percent (KLL seeds its compaction randomly, so two batch builds are not byte-identical either). Every ingestion-time stored output of those plans runs per sample.per_sample::per_sample_panes_apply_label_matchers.query_time_reference(query_run::*,query::*).