Skip to content

Commit aff95f2

Browse files
committed
special case bitwise ops when buffers are u64 aligned
1 parent 5516cf4 commit aff95f2

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

arrow-buffer/src/buffer/ops.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ where
8080
// if there is no prefix or suffix, both buffers are aligned and we can do the operation directly
8181
// on u64s
8282
// TODO also handle non empty suffixes by processing them separately
83-
if left_prefix.is_empty() && right_prefix.is_empty() && left_suffix.is_empty() && right_suffix.is_empty() {
83+
if left_prefix.is_empty()
84+
&& right_prefix.is_empty()
85+
&& left_suffix.is_empty()
86+
&& right_suffix.is_empty()
87+
{
8488
let result_u64s = left_u64s
8589
.iter()
8690
.zip(right_u64s.iter())
@@ -91,8 +95,6 @@ where
9195
}
9296
}
9397

94-
95-
9698
let left_chunks = left.bit_chunks(left_offset_in_bits, len_in_bits);
9799
let right_chunks = right.bit_chunks(right_offset_in_bits, len_in_bits);
98100

@@ -124,6 +126,21 @@ pub fn bitwise_unary_op_helper<F>(
124126
where
125127
F: FnMut(u64) -> u64,
126128
{
129+
// If the underlying buffer is aligned to u64, apply the operation directly on the u64 slices
130+
// to improve performance.
131+
if offset_in_bits == 0 && len_in_bits > 0 {
132+
unsafe {
133+
let (prefix, u64s, suffix) = left.as_slice().align_to::<u64>();
134+
// if there is no prefix or suffix, the buffer is aligned and we can do the operation directly
135+
// on u64s
136+
// TODO also handle non empty suffixes by processing them separately
137+
if prefix.is_empty() && suffix.is_empty() {
138+
let result_u64s = u64s.iter().map(|l| op(*l)).collect::<Vec<u64>>();
139+
return result_u64s.into();
140+
}
141+
}
142+
}
143+
127144
// reserve capacity and set length so we can get a typed view of u64 chunks
128145
let mut result =
129146
MutableBuffer::new(ceil(len_in_bits, 8)).with_bitset(len_in_bits / 64 * 8, false);

arrow-buffer/src/util/bit_chunk_iterator.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ impl<'a> BitChunks<'a> {
223223
pub fn new(buffer: &'a [u8], offset: usize, len: usize) -> Self {
224224
assert!(
225225
ceil(offset + len, 8) <= buffer.len(),
226-
"offset + len out of bounds"
226+
"offset + len out of bounds. Buffer length in bits: {}, requested offset: {offset}, len: {len}",
227+
buffer.len(),
227228
);
228229

229230
let byte_offset = offset / 8;

0 commit comments

Comments
 (0)