This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-11406-9d1a049a4b28c7e5bb974c69fc6b6063ddcaa424 in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
commit b77170d3c1c958b2bf3d3ccfa3287cbdc9dd7936 Author: Neil Conway <[email protected]> AuthorDate: Wed Oct 7 14:12:39 2026 +0000 bench(parquet): add list benchmarks that skip and read in short runs (#11406) # Which issue does this PR close? - N/A # Rationale for this change The `ListArray` benchmarks read whole batches of 8192 records. A reader applying a `RowSelection` with short runs instead alternates between `skip_records` and `read_records` calls of a few records each, so per-call costs in the level decoders matter much more. No benchmark measures this for lists. # What changes are included in this PR? Add `Int32List` cases that alternately skip and read runs of 1 record (the worst case) and of 32 records (by default, selections whose runs average fewer than 32 rows are read with a mask instead). # Are these changes tested? Benchmark-only change. # Are there any significant user-facing changes? No. --- parquet/benches/arrow_reader.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/parquet/benches/arrow_reader.rs b/parquet/benches/arrow_reader.rs index dadd4516cb..3b23628009 100644 --- a/parquet/benches/arrow_reader.rs +++ b/parquet/benches/arrow_reader.rs @@ -986,6 +986,28 @@ fn bench_array_reader_skip(mut array_reader: Box<dyn ArrayReader>) -> usize { total_count } +/// Alternately skips and reads `run_len` records, as when reading a row +/// selection made of short runs, and emits a batch every `BATCH_SIZE` records read +fn bench_array_reader_runs(mut array_reader: Box<dyn ArrayReader>, run_len: usize) -> usize { + let mut total_count = 0; + let mut batch_count = 0; + loop { + let skipped = array_reader.skip_records(run_len).unwrap(); + let read = array_reader.read_records(run_len).unwrap(); + total_count += skipped + read; + batch_count += read; + if batch_count >= BATCH_SIZE { + array_reader.consume_batch().unwrap(); + batch_count = 0; + } + if read < run_len { + break; + } + } + array_reader.consume_batch().unwrap(); + total_count +} + fn create_primitive_array_reader( page_iterator: impl PageIterator + 'static, column_desc: ColumnDescPtr, @@ -2654,6 +2676,17 @@ fn add_benches(c: &mut Criterion) { }); assert_eq!(count, EXPECTED_VALUE_COUNT); }); + let list_data = build_int32_list_page_iterator(int32_list_desc.clone(), 0.0, 0); + for run_len in [1, 32] { + let label = format!("no NULLs, skip and read in runs of {run_len}"); + group.bench_function(label, |b| { + b.iter(|| { + let reader = create_int32_list_reader(list_data.clone(), int32_list_desc.clone()); + count = bench_array_reader_runs(reader, run_len); + }); + assert_eq!(count, EXPECTED_VALUE_COUNT); + }); + } group.finish(); let mut group = c.benchmark_group("arrow_array_reader/ListArray/Fixed32List");
