Skip to content

perf: optimize arrays_zip perfect list zips#22285

Open
puneetdixit200 wants to merge 4 commits into
apache:mainfrom
puneetdixit200:codex/arrays-zip-perfect-zip
Open

perf: optimize arrays_zip perfect list zips#22285
puneetdixit200 wants to merge 4 commits into
apache:mainfrom
puneetdixit200:codex/arrays-zip-perfect-zip

Conversation

@puneetdixit200
Copy link
Copy Markdown

Which issue does this PR close?

Rationale for this change

arrays_zip currently uses the general MutableArrayData path even when all regular ListArray inputs are already perfectly aligned. In that case, the output list offsets match the inputs and each struct child column can reuse the corresponding input values array instead of copying one row at a time.

What changes are included in this PR?

  • Add a fast path for perfect regular ListArray zips that reuses the first input's offsets and clones the input values arrays into the output struct children.
  • Keep the existing general path for ragged inputs, LargeList, FixedSizeList, Null inputs, and null rows that would require padding.
  • Add unit coverage for offset/value reuse, zero-length null rows, and null rows with hidden values falling back to the general path.
  • Rename the no-null benchmark case to arrays_zip_perfect_zip_8192.

Are these changes tested?

Yes. Local checks run:

  • cargo fmt --all
  • cargo test -p datafusion-functions-nested
  • cargo clippy -p datafusion-functions-nested --all-targets --all-features -- -D warnings
  • CARGO_TARGET_DIR=C:\df-target cargo clippy --all-targets --all-features -- -D warnings
  • CARGO_TARGET_DIR=C:\df-target cargo bench -p datafusion-functions-nested --bench arrays_zip -- --warm-up-time 1 --measurement-time 2 --sample-size 10

Latest local benchmark sample:

  • arrays_zip_perfect_zip_8192: 11.234 µs 11.600 µs 12.045 µs
  • arrays_zip_10pct_nulls_8192: 4.3463 ms 4.5531 ms 4.7898 ms

Are there any user-facing changes?

No. This is an internal performance optimization with the same arrays_zip output semantics.## Which issue does this PR close?

Rationale for this change

arrays_zip currently uses the general MutableArrayData path even when all regular ListArray inputs are already perfectly aligned. In that case, the output list offsets match the inputs and each struct child column can reuse the corresponding input values array instead of copying one row at a time.

What changes are included in this PR?

  • Add a fast path for perfect regular ListArray zips that reuses the first input's offsets and clones the input values arrays into the output struct children.
  • Keep the existing general path for ragged inputs, LargeList, FixedSizeList, Null inputs, and null rows that would require padding.
  • Add unit coverage for offset/value reuse, zero-length null rows, and null rows with hidden values falling back to the general path.
  • Rename the no-null benchmark case to arrays_zip_perfect_zip_8192.

Are these changes tested?

Yes. Local checks run:

  • cargo fmt --all
  • cargo test -p datafusion-functions-nested
  • cargo clippy -p datafusion-functions-nested --all-targets --all-features -- -D warnings
  • CARGO_TARGET_DIR=C:\df-target cargo clippy --all-targets --all-features -- -D warnings
  • CARGO_TARGET_DIR=C:\df-target cargo bench -p datafusion-functions-nested --bench arrays_zip -- --warm-up-time 1 --measurement-time 2 --sample-size 10

Latest local benchmark sample:

  • arrays_zip_perfect_zip_8192: 11.234 µs 11.600 µs 12.045 µs
  • arrays_zip_10pct_nulls_8192: 4.3463 ms 4.5531 ms 4.7898 ms

Are there any user-facing changes?

No. This is an internal performance optimization with the same arrays_zip output semantics.

Copilot AI review requested due to automatic review settings May 16, 2026 23:01
@github-actions github-actions Bot added the functions Changes to functions implementation label May 16, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a fast-path to arrays_zip that can reuse existing offsets and value buffers when inputs are “perfectly aligned” list arrays, and updates benchmarks accordingly.

Changes:

  • Introduce try_perfect_list_zip fast-path and invoke it early from arrays_zip_inner
  • Add unit tests covering reuse behavior and fallback conditions
  • Rename the no-nulls benchmark case to reflect the new “perfect zip” scenario

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
datafusion/functions-nested/src/arrays_zip.rs Adds perfect-zip fast-path plus tests validating reuse and fallback behavior
datafusion/functions-nested/benches/arrays_zip.rs Renames benchmark to better represent the new fast-path scenario

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +360 to +397
for arr in &list_arrays {
if arr.len() != num_rows || arr.values().len() != values_len {
return Ok(None);
}
}

let nulls = if list_arrays.iter().any(|arr| arr.null_count() != 0) {
let mut null_builder = NullBufferBuilder::new(num_rows);
for row_idx in 0..num_rows {
let mut all_null = true;

for arr in &list_arrays {
if arr.is_null(row_idx) {
if arr.offsets()[row_idx + 1] != arr.offsets()[row_idx] {
return Ok(None);
}
} else {
all_null = false;
}
}

if all_null {
null_builder.append_null();
} else {
null_builder.append_non_null();
}
}

null_builder.finish()
} else {
None
};

for arr in &list_arrays {
if arr.offsets() != &offsets {
return Ok(None);
}
}
Comment on lines +335 to +350
fn try_perfect_list_zip(args: &[ArrayRef]) -> Result<Option<ArrayRef>> {
let mut list_arrays = Vec::with_capacity(args.len());
let mut struct_fields = Vec::with_capacity(args.len());

for (i, arg) in args.iter().enumerate() {
let arr = match arg.data_type() {
List(field) => {
struct_fields.push(Field::new(
format!("{}", i + 1),
field.data_type().clone(),
true,
));
as_list_array(arg)?
}
_ => return Ok(None),
};
Comment thread datafusion/functions-nested/src/arrays_zip.rs Outdated
puneetdixit200 and others added 3 commits May 17, 2026 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

functions Changes to functions implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optimize arrays_zip to avoid row-by-row copying in the perfect-zip case

2 participants