Skip to content

bench: measure projected Parquet scans across file boundaries - #27016

Merged
zhuqi-lucas merged 1 commit into
apache:mainfrom
sunchao:bench/parquet-cross-file-reads
Nov 4, 2026
Merged

zhuqi-lucas merged 1 commit into
apache:mainfrom
sunchao:bench/parquet-cross-file-reads

Conversation

@sunchao

@sunchao sunchao commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Which issue does this PR close?

Part of #26682.

Rationale for this change

When each Parquet file has one row group, a reader can hide the next file's data request by starting it while decoding the current file. A benchmark that scans several partitions concurrently can hide the same delay even when each reader waits for its current file to finish. This gives #23492 and the cross-file experiment on #24086 a shared, single-partition workload.

What changes are included in this PR?

  • Extend sql_query_with_io with a projected scan over 20 single-row-group files in one scan partition. The same SQL and bytes run against an in-memory store and a store with 100 ms of simulated read latency. Planning and data generation happen outside the timed loop. Each execution checks the sum of the selected column over 20 million rows.
  • Add a two-file object-store test. The full projection must read the selected column chunk once from each file and return all four values. With LIMIT 1, only one file's payload is needed. File statistics are disabled so the scan gets both files, and the assertions allow either file order.

What is the testing strategy for this PR?

cargo test -p datafusion --test core_integration object_store_access passed all 24 tests. The extended workspace suite passed 13,396 Rust tests and all 545 SQL logic files. Workspace formatting and Clippy with all targets and features passed. To reproduce the benchmark, run

cargo bench -p datafusion --bench sql_query_with_io -- parquet_cross_file_projection

Local Criterion baseline on the PR branch, using a release build on a shared host, four pinned CPUs and ten samples per store.

Store Estimated scan time 95% confidence interval
In memory 24.6 ms 24.3–24.9 ms
100 ms per read request 2.059 s 2.057–2.060 s

To check that the benchmark detects cross-file read-ahead, I also ran the same workload against the public cross-file prototype from #24086. Both arms used the same release binary on four pinned CPUs, with file-open depth 2, a 16 MiB read-ahead window and a shared 32 MiB budget. Only the eager first-read cap changed, from 0 to 16 MiB. I ran off/on/on/off, with ten samples per process. Each cell is the median of its two process medians.

Store on the prototype Eager reads off Eager reads on Elapsed time change
In memory 29.22 ms 30.73 ms 5.2% longer
100 ms per read request 2.065 s 1.036 s 49.8% shorter

The prototype roughly halved elapsed time on the simulated high-latency store and added about 1.5 ms on the in-memory control. Both configurations produced the same expected sum. A real object-store workload could have a different balance of I/O and decoding.

Are there any user-facing changes?

No. This adds benchmark and integration-test coverage.

@zhuqi-lucas zhuqi-lucas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sunchao — nice measurement infra. The request-pattern assertions are tight (footer reads excluded via the range cutoff) and the env-driven config makes prototype A/B easy.

@zhuqi-lucas
zhuqi-lucas added this pull request to the merge queue Nov 4, 2026
Merged via the queue into apache:main with commit caaf0fa Nov 4, 2026
43 of 45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants