Skip to content

feat(scan): run the V2 executor on the segment IO protocol - #10527

Draft
joseph-isaacs wants to merge 1 commit into
ji/segment-io-protocolfrom
ji/segment-io
Draft

joseph-isaacs wants to merge 1 commit into
ji/segment-io-protocolfrom
ji/segment-io

Conversation

@joseph-isaacs

@joseph-isaacs joseph-isaacs commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Stacked on #10568, which adds the segment IO protocol (vortex_io::segments).

This PR moves the planner-driven V2 scan from the byte-range vortex_io::request protocol onto the new protocol, then removes request. It serves the protocol with FileSegmentIo, which reads through each file's existing v1 segment source. V1 scans are unchanged. At runtime, V2 reads share the file's segment cache, request sharing and coalescing read driver, and no task or thread is added.

Changes

  • vortex-scan
    • Planner and Morsel drop the IoConsumer supertrait. They publish NeedsIO(Vec<IoRequest>) and receive deliver(key, result) once per successful fetch.
    • Run and Driver submit each root's requests to that root's SegmentIoSession, and hold the handles.
    • Each item's fetches finish through the item's own FuturesUnordered, so a poll_ready report yields exactly the fetches that finished. Run::poll_io replaces Run::complete.
    • The scripted test harness is a recording SegmentIoSession, and the driver tests are ported to it.
  • vortex-layout
    • ScanAdaptor fetches each segment once by IoKey::segment while any scan read of it is outstanding, and hands the result to every waiting read.
    • The filter planner (Add Filter/Split/Project planner and add Datafusion usage of this #10706) announces each segment once.
    • ScanFile carries the file's RegisteredSource, and each split reads through a new session of its service.
    • SegmentScanIo is removed, along with the byte-range index that ScanCache kept for it.
    • dictionary_values_are_reused_between_splits now writes codes and values to separate segments. Before, they shared a segment, which the adaptor now reads once.
  • vortex-file: segment_io::FileSegmentIo, one per VortexSession.
    • Size requests are answered at submit.
    • Segment requests call SegmentSource::request, which registers the read with the file's coalescing driver without starting it, so an announcement can widen a read, including another session's read.
    • Fetches and prefetches are polled once the whole batch is registered, then from poll_ready until they finish.
    • VortexFile::scan_file registers the file's segment source. A caching file keeps a single registration in its scan cache, and with_segment_source renews it.
    • TODO (in code): give the service its own read driver.
  • vortex-datafusion: the V2 opener shares a file's segment source across partitions through VortexFile::with_segment_source.
  • vortex-io: request is removed.

Checks run:

  • cargo clippy -p vortex-io -p vortex-scan -p vortex-layout -p vortex-file -p vortex-datafusion --all-targets --all-features -- -D warnings
  • cargo clippy -p compress-bench -p vortex-bench --all-targets -- -D warnings
  • cargo +nightly-2026-09-10 fmt on those crates
  • RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --no-deps -p vortex-io -p vortex-scan -p vortex-layout -p vortex-file --all-features
  • cargo test --lib: vortex-io (109), vortex-scan (58), vortex-layout (635), vortex-file (174), vortex-datafusion (773)
  • typos

API Changes

  • vortex_io::request is removed.
  • Planner and Morsel drop IoConsumer and gain deliver(IoKey, SourceResult). NeedsIO carries Vec<IoRequest>.
  • ScanFile.segments is replaced by ScanFile.segment_io: RegisteredSource.
  • New: vortex_file::segment_io::FileSegmentIo.

🤖 Generated with Claude Code

https://claude.ai/code/session_01N4PmceDHg8rFe5bgkhGFU9

@codspeed

codspeed Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 3 benchmarks

4 warnings, 1 note

⚠️ Walltime results may be unreliable

Some benchmarks used the Walltime instrument outside CodSpeed Macro Runners, which can make the results inconsistent.

Learn more about Macro Runners

See affected benchmarks

⚠️ Unable to measure the execution of 1 benchmark

This benchmark measured no execution time, so its result is not comparable and counts as unchanged. This usually happens when the compiler removes the code under test.

Prevent compiler optimizations

See affected benchmarks

⚠️ 21 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

ℹ️ 40 benchmarks have no flamegraph

The flamegraph wasn't generated: the symbols of the profiling trace could not be resolved, because no information about the language frames was collected.

See affected benchmarks

⚡ 6 improved benchmarks
❌ 3 regressed benchmarks
✅ 2399 untouched benchmarks
⏩ 12 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ CPU Simulation chunked_dict_primitive_canonical_into[f64, (1000, 1000, 10)] 151.5 µs 205.8 µs -26.41%
❌ Walltime bitpack_blocked_compress_avx2 6.7 µs 7.6 µs -11.33%
❌ CPU Simulation test_scan_scalar_at[int_float] 948.2 µs 1,059.2 µs -10.48%
⚡ Walltime filter_neon[8] 1,268 ns 902 ns +40.58%
⚡ Walltime threshold_neon[80] 4.6 µs 3.4 µs +35.19%
⚡ Walltime filter_neon[64] 2.2 µs 1.7 µs +29.9%
⚡ Walltime filter_neon[80] 2.8 µs 2.4 µs +15%
⚡ CPU Simulation prepare_and_compile[1000] 2.4 ms 2.2 ms +10.8%
⚡ CPU Simulation chunked_canonicalize_into[(20, 100, 16, 4)] 372 µs 338 µs +10.05%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing ji/segment-io (a5654f2) with ji/segment-io-protocol (8e2defb)

Open in CodSpeed

Footnotes

  1. 12 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@joseph-isaacs joseph-isaacs changed the title feat(io): a segment-keyed IO system for planner-driven scans feat(file): serve the segment IO protocol through files' segment sources Oct 16, 2026
@joseph-isaacs
joseph-isaacs changed the base branch from develop to ji/segment-io-protocol October 16, 2026 16:45
Switches the planner-driven scan from the byte-range `vortex_io::request`
protocol to `vortex_io::segments`, and serves it with a session-wide
`FileSegmentIo` that reads through files' v1 segment sources.

- vortex-scan: `Planner` and `Morsel` drop the `IoConsumer` supertrait,
  publish `NeedsIO(Vec<IoRequest>)`, and receive `deliver(key, result)` once
  per successful fetch. `Run`/`Driver` submit each root's requests to its
  `SegmentIoSession` and hold the handles; each item's fetches finish through
  its own `FuturesUnordered`, so a `poll_ready` report yields exactly the
  finished fetches. `Run::poll_io` replaces `Run::complete`. The scripted
  harness is a recording `SegmentIoSession`.
- vortex-layout: `ScanAdaptor` fetches each segment once by `IoKey::segment`
  while any scan read of it is outstanding, and hands the result to every
  waiting read. The filter planner announces each segment once. `ScanFile`
  carries the file's `RegisteredSource`, and each split reads through a new
  session of its service. `SegmentScanIo` and the cached byte-range index it
  needed are removed.
- vortex-file: `FileSegmentIo`, one per `VortexSession`. Size requests are
  answered at submit; segment requests call `SegmentSource::request`, so they
  share the file's segment cache, request sharing and coalescing read driver.
  `VortexFile::scan_file` registers the file's segment source, and a caching
  file keeps one registration in its scan cache, renewed with its segment
  source.
- vortex-datafusion: the V2 opener shares a file's segment source across
  partitions through `VortexFile::with_segment_source`.
- vortex-io: `request` is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N4PmceDHg8rFe5bgkhGFU9
Signed-off-by: Claude <noreply@anthropic.com>
@joseph-isaacs
joseph-isaacs force-pushed the ji/segment-io-protocol branch from 24ef18f to 8e2defb Compare October 23, 2026 23:56
@joseph-isaacs joseph-isaacs changed the title feat(file): serve the segment IO protocol through files' segment sources feat(scan): run the V2 executor on the segment IO protocol Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

CodSpeed Performance Analysis flags regressions on a5654f2. I don't think this PR causes them:

  • Which benchmarks: vortex-array's chunked_dict_primitive_canonical_into (CPU simulation) and FastLanes bit-packing walltime benchmarks (bitpack_blocked_compress_avx2, …).
  • What this PR changes: only the planner-driven scan's IO (vortex-io, vortex-scan, the V2 executor in vortex-layout, vortex-file's FileSegmentIo, and the DataFusion V2 opener). None of those benchmarks runs that code, and no array or encoding code changes.
  • Measurement: CodSpeed itself warns that base and head ran on different runner types, and that the walltime results ran outside its Macro Runners.
  • The same benchmark family on feat(io): a segment-keyed IO protocol for planner-driven scans #10568: the FastLanes walltime benchmarks also moved there, and that PR only adds an unused module.

No fix is needed, and I can't re-run CodSpeed from here. #10569 runs the same tree, so this applies to its CodSpeed report too.


Generated by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants