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-11193-26de48deafabfd1dd5f002a484d63c4bc38ae8a5 in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
commit f698c259f0fbba91ad667a8c1b27d617acd1a34d Author: Yifan Chen <[email protected]> AuthorDate: Fri Oct 2 17:47:02 2026 +0000 bench(variant): add list-index lookup with empty lists (#11193) # Which issue does this PR close? Related to #11101 and #11052. # Rationale for this change Add a small benchmark for `variant_get` list-index lookup when some rows are empty lists. # What changes are included in this PR? Two benchmark functions in the existing `variant_kernels` target, following the nearby cases. The first builds 8,192 rows alternating empty and two-element integer lists, then looks up index zero with Variant output. The same fixture is timed unshredded and shredded as a List of Int64. Fixture construction, shredding, and path setup are outside timing; options cloning and output destruction are included. The second restores the previously regressing small case: 64 one-element `[1]` lists shredded as List<Int64>, index 9 (all out of bounds), and Int64 output. It checks that all 64 results are null before timing. The benchmark name is `variant_get_list_index_all_oob_int64_64_rows`. # Are these changes tested? - `cargo bench --locked -p parquet-variant-compute --bench variant_kernels -- variant_get_list_index --test`: all three cases pass. - Focused Criterion runs completed the mixed-list cases and the all-OOB case (50 samples, 1 s warm-up, 3 s measurement). - `cargo test --locked -p parquet-variant-compute`: 367 unit tests and 13 doc tests passed for the previous revision; this benchmark-only follow-up was validated with the benchmark smoke run, Criterion, Clippy, and formatting. - `cargo clippy --locked -p parquet-variant-compute --all-targets --all-features -- -D warnings` - `cargo fmt --all -- --check`, `git diff --check`, and the repository spelling check with typos 1.37.0 pass. The benchmark runs on the existing baseline without asserting the missing-index validity behavior that #11052 fixes. Unshredded and shredded outputs currently differ in validity on empty rows, so these timings do not establish an equivalent-output speedup or the cost of that correctness fix. The earlier ~24% overhead observed in the separate 64-row all-OOB Int64 case remains unresolved; adding its benchmark does not change that result. # Are there any user-facing changes? No. This only adds a benchmark; production code and dependencies are unchanged. # AI usage OpenAI Codex generated this benchmark revision, ran the validation, and drafted this description and review reply. --- parquet-variant-compute/benches/variant_kernels.rs | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/parquet-variant-compute/benches/variant_kernels.rs b/parquet-variant-compute/benches/variant_kernels.rs index 373a66cdd8..0d35d68901 100644 --- a/parquet-variant-compute/benches/variant_kernels.rs +++ b/parquet-variant-compute/benches/variant_kernels.rs @@ -180,6 +180,55 @@ pub fn variant_get_bench(c: &mut Criterion) { }); } +pub fn variant_get_list_index_bench(c: &mut Criterion) { + let mut builder = VariantArrayBuilder::new(8192); + for i in 0..8192 { + let mut list = builder.new_list(); + // Alternate empty lists with two-element lists to exercise missing and present indexes. + if i % 2 != 0 { + list.append_value(Variant::Int64(i)); + list.append_value(Variant::Int64(i + 1)); + } + list.finish(); + } + let variant_array = builder.build(); + let list_type = DataType::List(Arc::new(Field::new("item", DataType::Int64, true))); + let shredded = shred_variant(&variant_array, &list_type).unwrap(); + let options = GetOptions::new_with_path(VariantPath::from(0)); + + let input = ArrayRef::from(variant_array); + c.bench_function("variant_get_list_index_unshredded", |b| { + b.iter(|| variant_get(&input, options.clone()).unwrap()) + }); + + let input = ArrayRef::from(shredded); + c.bench_function("variant_get_list_index_shredded", |b| { + b.iter(|| variant_get(&input, options.clone()).unwrap()) + }); +} + +pub fn variant_get_list_index_all_oob_int64_bench(c: &mut Criterion) { + let mut builder = VariantArrayBuilder::new(64); + for _ in 0..64 { + let mut list = builder.new_list(); + list.append_value(Variant::Int64(1)); + list.finish(); + } + let variant_array = builder.build(); + let list_type = DataType::List(Arc::new(Field::new("item", DataType::Int64, true))); + let input = ArrayRef::from(shred_variant(&variant_array, &list_type).unwrap()); + let options = GetOptions::new_with_path(VariantPath::from(9)) + .with_as_type(Some(Arc::new(Field::new("value", DataType::Int64, true)))); + let result = variant_get(&input, options.clone()).unwrap(); + assert_eq!(result.data_type(), &DataType::Int64); + assert_eq!(result.len(), 64); + assert_eq!(result.null_count(), 64); + + c.bench_function("variant_get_list_index_all_oob_int64_64_rows", |b| { + b.iter(|| variant_get(&input, options.clone()).unwrap()) + }); +} + pub fn variant_get_shredded_utf8_bench(c: &mut Criterion) { let variant_array = create_shredded_utf8_variant_array(8192); let input = ArrayRef::from(variant_array); @@ -474,6 +523,8 @@ pub fn variant_get_binary_from_string_bench(c: &mut Criterion) { criterion_group!( benches, variant_get_bench, + variant_get_list_index_bench, + variant_get_list_index_all_oob_int64_bench, variant_get_shredded_utf8_bench, variant_get_unshredded_object_path_bench, shred_variant_partial_object_bench,
