diff --git a/arrow-buffer/src/buffer/ops.rs b/arrow-buffer/src/buffer/ops.rs index 05593504b1cf..32259c2afa1d 100644 --- a/arrow-buffer/src/buffer/ops.rs +++ b/arrow-buffer/src/buffer/ops.rs @@ -61,6 +61,8 @@ where /// Apply a bitwise operation `op` to two inputs and return the result as a Buffer. /// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits. +/// +/// This is a comment for testing purposes pub fn bitwise_bin_op_helper( left: &Buffer, left_offset_in_bits: usize, @@ -72,6 +74,30 @@ pub fn bitwise_bin_op_helper( where F: FnMut(u64, u64) -> u64, { + // If the underlying buffers are aligned to u64 we can apply the operation directly on the u64 slices + // to improve performance. + if left_offset_in_bits == 0 && right_offset_in_bits == 0 { + unsafe { + let (left_prefix, left_u64s, left_suffix) = left.as_slice().align_to::(); + let (right_prefix, right_u64s, right_suffix) = right.as_slice().align_to::(); + // if there is no prefix or suffix, both buffers are aligned and we can do the operation directly + // on u64s + // TODO also handle non empty suffixes by processing them separately + if left_prefix.is_empty() + && right_prefix.is_empty() + && left_suffix.is_empty() + && right_suffix.is_empty() + { + let result_u64s = left_u64s + .iter() + .zip(right_u64s.iter()) + .map(|(l, r)| op(*l, *r)) + .collect::>(); + return result_u64s.into(); + } + } + } + let left_chunks = left.bit_chunks(left_offset_in_bits, len_in_bits); let right_chunks = right.bit_chunks(right_offset_in_bits, len_in_bits);