Skip to content

fix: Cooperate while splitting cached batches - #184

Merged
osipovartem merged 1 commit into
df55-physical-udf-instancefrom
fix/batch-split-cooperation-20261113
Nov 13, 2026
Merged

osipovartem merged 1 commit into
df55-physical-udf-instancefrom
fix/batch-split-cooperation-20261113

Conversation

@osipovartem

Copy link
Copy Markdown
Collaborator

Summary

  • Make cached BatchSplitStream outputs consume the existing cooperative scheduling budget. They previously bypassed the upstream yield points.
  • Share the existing Tokio, Tokio-fallback and per-stream policies without changing the public CooperativeStream API.
  • Keep first-slice and unsplit upstream-polled outputs free of an additional budget charge. Preserve row order, zero-copy slices, errors, empty batches and split metrics.

Targets df55-physical-udf-instance, the runtime branch used by Rustice, rather than the diverged upstream-sync branch.

Validation

  • cargo fmt --all
  • Strict workspace Clippy: --all-targets --all-features -- -D warnings
  • Complete ./dev/rust_lint.sh, including rustdoc; repository Rust 1.97 and CI-pinned license/typo tools
  • Extended workspace tests: 10,781 passed, zero failed, 10 ignored
  • Focused stream/cooperation tests: 11 passed in each of the default, per_stream and tokio_fallback policies
  • Independent source review completed; no remaining blocking correctness, API or test findings

Local Cost Screen

Same native MemoryStream -> cooperative -> BatchSplitStream -> drain pipeline, frozen dependency/feature graphs and explicit optimized CI profile (opt-level=1, Rust 1.99). Inputs contain 1M Int32 rows; batch size 1,024 produces 977 batches. Order, buffer sharing and metrics are checked before timing; every timed sample checks row/batch totals.

Eight fixed-CPU processes follow ABBAABBA order, four per revision, with 20 warmups and 1,001 samples per case/process. Medians below are the median of four run medians; tails pool 4,004 samples per revision/case.

Case Median Before/After (us) p95 Before/After (us) p99 Before/After (us)
Unsplit fast path 58.624 / 58.039 70.943 / 69.466 87.378 / 88.435
Cached splitting 68.625 / 66.895 83.263 / 88.737 100.924 / 115.033

The cached-path tail increase is explicitly accepted as an observed cost of restoring cooperation: +5.474 us at p95 and +14.109 us at p99 in this synthetic screen. The existing 128-unit policy is retained; ordinary unsplit outputs receive no new charge and slicing/allocation behavior is unchanged.

The earlier, separately retained short cohort (two warmups, 101 samples per process) showed larger cached-tail increases: +16.92% at p95 and +33.93% at p99. The cohorts are not pooled, and attribution of every tail increment remains incomplete. Independent review accepted this narrow fairness/cancellation tradeoff. These workstation measurements establish neither a production latency bound nor a general query speedup.

@osipovartem
osipovartem merged commit 58ce21b into df55-physical-udf-instance Nov 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant