Repository navigation
feat: share Top-K bounds between sibling tasks - #861
Draft
joybestourous wants to merge 2 commits into
Draft
joybestourous wants to merge 2 commits into
joybestourous wants to merge 2 commits into
Conversation
Add pruning-friendly and no-pruning scan workloads with ordinary localhost execution, exact result checks, and observed worker filter application. Include fixed-query resource windows alongside Criterion execution measurements. Environment: Datadog workspace Co-Authored-By: Codex GPT-6 <noreply@localhost>
Add an opt-in configuration that routes existing merged Top-K snapshots to eligible producer tasks. Attach a separate remote filter through DataFusion pushdown so shared updates preserve each task's local producer state. Environment: Datadog workspace Co-Authored-By: Codex GPT-6 <noreply@localhost>
joybestourous
force-pushed
the
joy/codex/sibling-topk-sharing
branch
from
November 10, 2026 22:36
c8a9096 to
4f263e8
Compare
This branch has not been deployed
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.
Motivation
A task executing
ORDER BY ... LIMIT Kcan discover a useful cutoff while sibling tasks continue scanning weaker candidates. This adds opt-in sharing of those bounds so siblings can prune remaining work, while keeping each task's own Top-K state independent.This PR remains draft, stacked on the independent benchmark prerequisite, based on upstream
cb6c9c4. Feature-only diff.Design
SiblingTopKConfigthrough the existing option-extension API. Existing remote, general dynamic-filter, and Top-K pushdown settings must also permit sharing.AND; join-filter merge rules are unchanged.The final merge still chooses the result; sharing does not compute an exact global kth row early. DataFusion's NULL ordering and ordinary
LIMITtie semantics remain. Coordinator and workers must all support the feature before enabling it; unchanged messages do not make mixed-version opt-in safe.Validation and measurements
Fresh rebased validation passed 496 tests, with 3 ignored, the example, formatting, and CI-scoped library/Iceberg Clippy with
-D warnings. The public-path activation test proves remote Parquet pruning while the receiver's local bound remains unrestricted. Other coverage includes projection/multiple keys/NULLs/ties, disabled settings, under-K inputs, inner-fetch barriers, joins, and unsupported/delegating plans. Both release builds, four smoke cases per arm, and final benchmark Clippy passed. GitHub CI for this head failed before creating any jobs or logs; the cause is unavailable and rerunning requires a maintainer. CI is not green.Measured baseline
5b80d0b45a6558df8d92e78863e4ee95929276f9→ feature4f263e81eb3287d85ab1efeaba9da82768676d71, on 2026-11-10, ARM Neoverse-N1, Linux 6.8/aarch64, affinity 0–7, Rust 1.95 release builds and the same lockfile. Values are median paired candidate/baseline ratios [observed pair ranges]; RSS is instead the paired change in MiB. Five pairs per measurement type; effective fractions are from resource runs.Pruning scan bytes fell from median 16.003 → 4.001 MiB/query and 65.386 → 56.385 MiB/query, paired ratios 0.250 and 0.861 [0.818–0.897]. Control bytes stayed identical at 32.511 and 130.042 MiB/query, with no group/range pruning. Useful bounds reached 150/150 and 100/100 pruning queries, and 100/100 in each control despite zero effective queries. Sharing reduced work in the pruning cases; controls paid about 7.8%/7.5% collection-time and 0.4%/6.4% instrumented CPU overhead. Every RSS range crosses zero, so no consistent memory change is established.
All 22 TPC-H SF1 queries completed with matching row counts and no errors. TOTAL, the sum of per-query elapsed-time medians, had paired ratio 0.993 [0.990–1.004] over three pairs. The option remains disabled by default: these synthetic/local results show conditional savings and costs, not a general production benefit.
Measurement scope, reproduction, validation limits, and scaling costs
The prerequisite uses two/eight actual scan tasks, two partitions per task, four Tokio threads, and ordinary localhost gRPC. Each task adds a Parquet file of 32 groups × 65,536 rows; eight tasks mean four times the input, not constant-work scaling. One layout allows early high bounds to prune low groups; the control has an excluded maximum-valued sentinel in every group. Row filtering and page indexes are disabled. No scan waits for a bound; correct queries remain included when remote effects are absent.
Every focused query checks complete ordered fixture-derived values and actual worker assignments. Effectiveness requires a useful remote predicate, pruning counters, and scan rows below a conservative local-only bound, covering row-group pruning/file-range stopping and discounting empty fragments. Scan bytes are separate Parquet-reader counters, not physical disk/network traffic. The filesystem is warm. A final useful bound alone is not proof that it helped execution.
Criterion and resources each use five alternating matched pairs without concurrent builds or other intentional benchmarks. Collection timing excludes setup, planning, and checks after collection; worker-completion observations can overlap collection. Criterion counts include calibration, warmup, and measured calls: candidate effects were 350/350, 100/115, 0/115, and 0/65 in table order, with useful bounds in every candidate query.
Fixed-work resources use fresh processes with 30 queries/run for pruning/2 and 20 for each other case, 900 total queries across both arms. The marked window includes planning, execution, observation, and checking. Process CPU includes feature-dependent observer work and is neither production-only overhead nor an upper bound on it. Sampled RSS can miss transient peaks; lifetime high-water RSS includes setup and is separate. All workers share one process, so results do not attribute resources to coordinator/individual workers. No resource pairs were rejected; no-effect queries were not discarded. Producer reports do not measure unique cutoffs or dynamic-control traffic bytes.
Measured executable source inputs match the signed revisions above. The baseline includes the independent benchmark on upstream
cb6c9c4; the candidate includes this feature and the benchmark setup opt-in. Workload/observer code is otherwise identical. Both use lockfile SHA-2568d9b2764248dcf2fed37f62659502a603a06ac8436b13cd4456ad444e30f4382, Rust 1.95.0, Clang 20.1.8 with LLD, release optimization, incremental compilation off, and four build jobs. Use separate build directories, build before measurement, and alternate the two arms:The benchmark README documents fixed-work mode. Use
TOPK_RESOURCE_CASE=pruning/2 TOPK_RESOURCE_QUERIES=30, or 20 queries for the other cases, and sample the benchmark process only betweenresource_begin/resource_end.TPC-H used a separate candidate-only local adapter, not a published runner change: in
datafusion/distributed-benchmarks/src/run.rs, importSiblingTopKConfigfromdatafusion_distributed, then insert this inRunOpt::run_localimmediately beforebackend.configure_session(builder).build():Leave the baseline unchanged. Build each
dfbenchseparately; the focused observer is a different target and is not indfbench. Generate one shared dataset and run each executable in three AB/BA/AB pairs:SF1 used 638,992,025 bytes with default 128-MiB maximum files, dictionary pages, and unsorted generation; available disk prevented SF10. All five iterations, including the first, enter each query median; TOTAL sums all 22 medians without integer truncation. Existing elapsed timing includes planning/collection and q15 setup. The standard local-worker shortcut and localhost topology are equal across arms. All 660 query iterations succeeded with matching row counts, but full values and sibling activation in each suite query were not checked. The suite has no CPU/RSS instrumentation and does not qualify SF10 or remote-host behavior.
Fresh tests were 349 unit + 128 integration + 19 doctest passes, with 3 ignored. The ordinary integration feature set does not enable every benchmark/chaos suite. Current CI-scoped library/Iceberg Clippy passed; the known unrelated whole-workspace
remote-workerlint failure was not rerun. Historical sensitivity tests are not claimed as fresh rebase validation. No staging/production experiment or full-workspace CI parity is claimed.The registry keeps the latest bound per producer, not every historical update. With N producers and N recipients, full-predicate fan-out can require O(N²) payload-copy work per merged update; receivers also decode/remap snapshots. Existing unbounded control queues can retain obsolete snapshots for slow recipients. Arrow's memory pool does not account for all these allocations. This patch adds no rate limiting, queue coalescing, strongest-bound reduction, or new telemetry.