Skip to content

Commit 6e4606d

Browse files
committed
polish
Signed-off-by: Alexander Droste <[email protected]>
1 parent b6dacd7 commit 6e4606d

File tree

4 files changed

+46
-338
lines changed

4 files changed

+46
-338
lines changed

vortex-buffer/src/bit/buf.rs

Lines changed: 5 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -440,14 +440,13 @@ impl BitBuffer {
440440
for bit_idx in 0..bits_in_first_byte {
441441
let is_set = (byte & (1 << (start_bit_in_byte + bit_idx))) != 0;
442442
f(bit_pos, is_set);
443-
bit_pos += 1;
444443
}
445444

445+
bit_pos += bits_in_first_byte;
446446
current_byte += 1;
447447
}
448448

449-
let bits_remaining = total_bits - bit_pos;
450-
let complete_bytes = bits_remaining / 8;
449+
let complete_bytes = (total_bits - bit_pos) / 8;
451450

452451
// Process complete bytes.
453452
for byte_idx in 0..complete_bytes {
@@ -458,87 +457,17 @@ impl BitBuffer {
458457
f(bit_pos + byte_idx * 8 + bit_idx, is_set);
459458
}
460459
}
460+
bit_pos += complete_bytes * 8;
461461
current_byte += complete_bytes;
462462

463463
// Handle remaining bits at the end.
464-
let remaining_bits = bits_remaining % 8;
464+
let remaining_bits = (total_bits - bit_pos) % 8;
465465
if remaining_bits > 0 {
466-
let bit_idx_start = bit_pos + complete_bytes * 8;
467466
let byte = unsafe { *buffer_ptr.add(current_byte) };
468467

469468
for bit_idx in 0..remaining_bits {
470469
let is_set = (byte & (1 << bit_idx)) != 0;
471-
f(bit_idx_start + bit_idx, is_set);
472-
}
473-
}
474-
}
475-
476-
/// Iterate through bits in a buffer in reverse.
477-
///
478-
/// # Arguments
479-
///
480-
/// * `f` - Callback function taking (bit_index, is_set)
481-
///
482-
/// # Panics
483-
///
484-
/// Panics if the range is outside valid bounds of the buffer.
485-
#[inline]
486-
pub fn iter_bits_reverse<F>(&self, mut f: F)
487-
where
488-
F: FnMut(usize, bool),
489-
{
490-
let total_bits = self.len;
491-
if total_bits == 0 {
492-
return;
493-
}
494-
495-
let buffer_ptr = self.buffer.as_ptr();
496-
let offset = self.offset;
497-
let start_byte = offset / 8;
498-
let start_bit_in_byte = offset % 8;
499-
let mut bit_pos = total_bits;
500-
501-
let bits_in_first_byte = if start_bit_in_byte > 0 {
502-
(8 - start_bit_in_byte).min(total_bits)
503-
} else {
504-
0
505-
};
506-
507-
let bits_after_first = total_bits - bits_in_first_byte;
508-
let first_byte_offset = if start_bit_in_byte > 0 { 1 } else { 0 };
509-
let complete_bytes = (bits_after_first - bits_after_first % 8) / 8;
510-
let trailing_bits = bits_after_first % 8;
511-
512-
// Handle remaining bit at the end.
513-
if trailing_bits > 0 {
514-
let byte = unsafe { *buffer_ptr.add(start_byte + first_byte_offset + complete_bytes) };
515-
516-
for bit_idx in (0..trailing_bits).rev() {
517-
bit_pos -= 1;
518-
let is_set = (byte & (1 << bit_idx)) != 0;
519-
f(bit_pos, is_set);
520-
}
521-
}
522-
523-
// Process complete bytes.
524-
for byte_idx in (0..complete_bytes).rev() {
525-
let byte = unsafe { *buffer_ptr.add(start_byte + first_byte_offset + byte_idx) };
526-
527-
for bit_idx in (0..8).rev() {
528-
bit_pos -= 1;
529-
let is_set = (byte & (1 << bit_idx)) != 0;
530-
f(bit_pos, is_set);
531-
}
532-
}
533-
534-
// Handle incomplete first byte.
535-
if bits_in_first_byte > 0 {
536-
let byte = unsafe { *buffer_ptr.add(start_byte) };
537-
538-
for bit_idx in (0..bits_in_first_byte).rev() {
539-
bit_pos -= 1;
540-
let is_set = (byte & (1 << (start_bit_in_byte + bit_idx))) != 0;
541-
f(bit_pos, is_set);
470+
f(bit_pos + bit_idx, is_set);
542471
}
543472
}
544473
}
@@ -657,31 +586,6 @@ mod tests {
657586
}
658587
}
659588

660-
#[rstest]
661-
#[case(5)]
662-
#[case(8)]
663-
#[case(10)]
664-
#[case(13)]
665-
#[case(16)]
666-
#[case(23)]
667-
#[case(100)]
668-
fn test_iter_bits_reverse(#[case] len: usize) {
669-
let buf = BitBuffer::collect_bool(len, |i| i % 2 == 0);
670-
671-
let mut collected = Vec::new();
672-
buf.iter_bits_reverse(|idx, is_set| {
673-
collected.push((idx, is_set));
674-
});
675-
676-
assert_eq!(collected.len(), len);
677-
678-
for (i, (idx, is_set)) in collected.iter().enumerate() {
679-
let expected_idx = len - 1 - i;
680-
assert_eq!(*idx, expected_idx);
681-
assert_eq!(*is_set, expected_idx % 2 == 0);
682-
}
683-
}
684-
685589
#[rstest]
686590
#[case(3, 5)]
687591
#[case(3, 8)]
@@ -704,29 +608,4 @@ mod tests {
704608
assert_eq!(is_set, (offset + idx) % 2 == 0);
705609
}
706610
}
707-
708-
#[rstest]
709-
#[case(3, 5)]
710-
#[case(3, 8)]
711-
#[case(5, 10)]
712-
#[case(2, 16)]
713-
fn test_iter_bits_reverse_with_offset(#[case] offset: usize, #[case] len: usize) {
714-
let total_bits = offset + len;
715-
let buf = BitBuffer::collect_bool(total_bits, |i| i % 2 == 0);
716-
let buf_with_offset = BitBuffer::new_with_offset(buf.inner().clone(), len, offset);
717-
718-
let mut collected = Vec::new();
719-
buf_with_offset.iter_bits_reverse(|idx, is_set| {
720-
collected.push((idx, is_set));
721-
});
722-
723-
assert_eq!(collected.len(), len);
724-
725-
for (i, (idx, is_set)) in collected.iter().enumerate() {
726-
let expected_idx = len - 1 - i;
727-
assert_eq!(*idx, expected_idx);
728-
// The bits should match the original buffer at positions offset + expected_idx
729-
assert_eq!(*is_set, (offset + expected_idx) % 2 == 0);
730-
}
731-
}
732611
}

vortex-compute/benches/expand_buffer.rs

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,30 @@
33

44
//! Expand benchmarks for `Buffer`.
55
6-
use divan::Bencher;
7-
use vortex_buffer::{Buffer, BufferMut};
6+
use vortex_buffer::Buffer;
87
use vortex_compute::expand::Expand;
98
use vortex_mask::Mask;
109

10+
// buffer size, selectivity
11+
const PARAMETERS: &[(usize, f64)] = &[
12+
(256, 0.1),
13+
(256, 0.5),
14+
(256, 0.9),
15+
(1024, 0.1),
16+
(1024, 0.5),
17+
(1024, 0.9),
18+
(4096, 0.1),
19+
(4096, 0.5),
20+
(4096, 0.9),
21+
(16384, 0.1),
22+
(16384, 0.5),
23+
(16384, 0.9),
24+
];
25+
1126
fn main() {
1227
divan::main();
1328
}
1429

15-
const BUFFER_SIZE: usize = 1024;
16-
17-
const SELECTIVITIES: &[f64] = &[
18-
0.01, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 0.99,
19-
];
20-
2130
fn create_test_buffer<T>(size: usize) -> Buffer<T>
2231
where
2332
T: Copy + Default + From<u8> + Send + 'static,
@@ -30,18 +39,6 @@ where
3039
Buffer::from(data)
3140
}
3241

33-
fn create_test_buffer_mut<T>(size: usize) -> BufferMut<T>
34-
where
35-
T: Copy + Default + From<u8> + Send + 'static,
36-
{
37-
let mut data = Vec::with_capacity(size);
38-
for i in 0..size {
39-
#[expect(clippy::cast_possible_truncation)]
40-
data.push(T::from((i % 256) as u8));
41-
}
42-
Buffer::from(data).into_mut()
43-
}
44-
4542
fn generate_mask(len: usize, selectivity: f64) -> Mask {
4643
let mut selection = vec![false; len];
4744
let mut indices: Vec<usize> = (0..len).collect();
@@ -61,35 +58,20 @@ fn generate_mask(len: usize, selectivity: f64) -> Mask {
6158
Mask::from_iter(selection)
6259
}
6360

64-
#[divan::bench(types = [u8, u32, u64], args = SELECTIVITIES, sample_count = 1000)]
65-
fn expand_copy<T: Copy + Default + From<u8> + Send + 'static>(bencher: Bencher, selectivity: f64) {
61+
#[divan::bench(types = [u8, u32, u64], args = PARAMETERS, sample_count = 1000)]
62+
fn expand_buffer<T: Copy + Default + From<u8> + Send + 'static>(
63+
bencher: divan::Bencher,
64+
(buffer_size, selectivity): (usize, f64),
65+
) {
6666
bencher
6767
.with_inputs(|| {
68-
let mask = generate_mask(BUFFER_SIZE, selectivity);
68+
let mask = generate_mask(buffer_size, selectivity);
6969
let true_count = mask.true_count();
7070
let buffer = create_test_buffer::<T>(true_count);
7171
(buffer, mask)
7272
})
73-
.bench_values(|(buffer, mask)| {
74-
let result = buffer.expand(&mask);
73+
.bench_refs(|(buffer, mask)| {
74+
let result = buffer.expand(mask);
7575
divan::black_box(result);
7676
});
7777
}
78-
79-
#[divan::bench(types = [u8, u32, u64], args = SELECTIVITIES, sample_count = 1000)]
80-
fn expand_inplace<T: Copy + Default + From<u8> + Send + 'static>(
81-
bencher: Bencher,
82-
selectivity: f64,
83-
) {
84-
bencher
85-
.with_inputs(|| {
86-
let mask = generate_mask(BUFFER_SIZE, selectivity);
87-
let true_count = mask.true_count();
88-
let buffer = create_test_buffer_mut::<T>(true_count);
89-
(buffer, mask)
90-
})
91-
.bench_values(|(mut buffer, mask)| {
92-
(&mut buffer).expand(&mask);
93-
divan::black_box(buffer);
94-
});
95-
}

0 commit comments

Comments
 (0)