@@ -6,8 +6,11 @@ use std::iter::Iterator;
66use arrow_buffer:: BooleanBuffer ;
77use arrow_buffer:: BooleanBufferBuilder ;
88use divan:: Bencher ;
9+ use vortex_buffer:: Alignment ;
910use vortex_buffer:: BitBuffer ;
1011use vortex_buffer:: BitBufferMut ;
12+ use vortex_buffer:: BufferMut ;
13+ use vortex_buffer:: collect_bool_words;
1114
1215fn main ( ) {
1316 // Pre-warm CPUID feature detection so the one-time probe cost is never
@@ -32,12 +35,45 @@ impl FromIterator<bool> for Arrow<BooleanBuffer> {
3235}
3336
3437const INPUT_SIZE : & [ usize ] = & [ 128 , 1024 , 2048 , 16_384 , 65_536 ] ;
38+ // CodSpeed's Divan adapter measures one generated input per benchmark URI, so keep
39+ // allocator alignment out of run-to-run comparisons.
40+ const BENCH_ALIGNMENT : Alignment = Alignment :: new ( 128 ) ;
3541
3642#[ inline]
3743fn true_count_pattern ( i : usize ) -> bool {
3844 ( i. is_multiple_of ( 3 ) ) ^ ( i. is_multiple_of ( 11 ) )
3945}
4046
47+ fn bit_buffer_with_capacity ( capacity : usize ) -> BitBufferMut {
48+ BitBufferMut :: from_buffer (
49+ BufferMut :: with_capacity_aligned ( capacity. div_ceil ( 8 ) , BENCH_ALIGNMENT ) ,
50+ 0 ,
51+ 0 ,
52+ )
53+ }
54+
55+ fn bit_buffer_mut_from_fn < F > ( len : usize , f : F ) -> BitBufferMut
56+ where
57+ F : FnMut ( usize ) -> bool ,
58+ {
59+ let num_words = len. div_ceil ( 64 ) ;
60+ let mut buffer = BufferMut :: < u64 > :: with_capacity_aligned ( num_words, BENCH_ALIGNMENT ) ;
61+ // SAFETY: `collect_bool_words` writes every word before any read.
62+ unsafe { buffer. set_len ( num_words) } ;
63+ collect_bool_words ( buffer. as_mut_slice ( ) , len, f) ;
64+
65+ let mut bytes = buffer. into_byte_buffer ( ) ;
66+ bytes. truncate ( len. div_ceil ( 8 ) ) ;
67+ BitBufferMut :: from_buffer ( bytes, 0 , len)
68+ }
69+
70+ fn bit_buffer_from_fn < F > ( len : usize , f : F ) -> BitBuffer
71+ where
72+ F : FnMut ( usize ) -> bool ,
73+ {
74+ bit_buffer_mut_from_fn ( len, f) . freeze ( )
75+ }
76+
4177#[ cfg( not( codspeed) ) ]
4278#[ divan:: bench( args = INPUT_SIZE ) ]
4379fn from_iter_arrow ( n : usize ) {
@@ -52,7 +88,7 @@ fn from_iter_bit_buffer(n: usize) {
5288#[ divan:: bench( args = INPUT_SIZE ) ]
5389fn append_vortex_buffer ( bencher : Bencher , length : usize ) {
5490 bencher
55- . with_inputs ( || ( BitBufferMut :: with_capacity ( length) , length) )
91+ . with_inputs ( || ( bit_buffer_with_capacity ( length) , length) )
5692 . bench_refs ( |( buffer, length) | {
5793 for idx in 0 ..* length {
5894 buffer. append ( idx % 2 == 0 ) ;
@@ -74,7 +110,7 @@ fn append_arrow_buffer(bencher: Bencher, length: usize) {
74110#[ divan:: bench( args = INPUT_SIZE ) ]
75111fn append_n_vortex_buffer ( bencher : Bencher , length : usize ) {
76112 bencher
77- . with_inputs ( || ( BitBufferMut :: with_capacity ( length) , length, true ) )
113+ . with_inputs ( || ( bit_buffer_with_capacity ( length) , length, true ) )
78114 . bench_refs ( |( buffer, length, boolean) | {
79115 for _ in 0 ..100 {
80116 buffer. append_n ( * boolean, * length / 100 ) ;
@@ -97,8 +133,8 @@ fn append_n_arrow_buffer(bencher: Bencher, length: usize) {
97133fn append_buffer_vortex_buffer ( bencher : Bencher , length : usize ) {
98134 bencher
99135 . with_inputs ( || {
100- let source = BitBuffer :: from_iter ( ( 0 .. length / 100 ) . map ( |i| i % 2 == 0 ) ) ;
101- let dest = BitBufferMut :: with_capacity ( length) ;
136+ let source = bit_buffer_from_fn ( length / 100 , |i| i % 2 == 0 ) ;
137+ let dest = bit_buffer_with_capacity ( length) ;
102138 ( source, dest)
103139 } )
104140 . bench_refs ( |( source, dest) | {
@@ -129,7 +165,7 @@ fn append_buffer_arrow_buffer(bencher: Bencher, length: usize) {
129165
130166#[ divan:: bench( args = INPUT_SIZE ) ]
131167fn value_vortex_buffer ( bencher : Bencher , length : usize ) {
132- let buffer = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) ;
168+ let buffer = bit_buffer_from_fn ( length, |i| i % 2 == 0 ) ;
133169 bencher. with_inputs ( || & buffer) . bench_refs ( |buffer| {
134170 for idx in 0 ..length {
135171 divan:: black_box ( buffer. value ( idx) ) ;
@@ -149,7 +185,7 @@ fn value_arrow_buffer(bencher: Bencher, length: usize) {
149185
150186#[ divan:: bench( args = INPUT_SIZE ) ]
151187fn slice_vortex_buffer ( bencher : Bencher , length : usize ) {
152- let buffer = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) ;
188+ let buffer = bit_buffer_from_fn ( length, |i| i % 2 == 0 ) ;
153189 bencher
154190 . with_inputs ( || ( & buffer, length / 2 ) )
155191 . bench_refs ( |( buffer, mid) | {
@@ -172,7 +208,7 @@ fn slice_arrow_buffer(bencher: Bencher, length: usize) {
172208
173209#[ divan:: bench( args = INPUT_SIZE ) ]
174210fn true_count_vortex_buffer ( bencher : Bencher , length : usize ) {
175- let buffer = BitBuffer :: from_iter ( ( 0 .. length) . map ( true_count_pattern) ) ;
211+ let buffer = bit_buffer_from_fn ( length, true_count_pattern) ;
176212
177213 bencher
178214 . with_inputs ( || & buffer)
@@ -194,8 +230,8 @@ fn true_count_arrow_buffer(bencher: Bencher, length: usize) {
194230
195231#[ divan:: bench( args = INPUT_SIZE ) ]
196232fn bitwise_and_vortex_buffer ( bencher : Bencher , length : usize ) {
197- let a = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) ;
198- let b = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 3 == 0 ) ) ;
233+ let a = bit_buffer_from_fn ( length, |i| i % 2 == 0 ) ;
234+ let b = bit_buffer_from_fn ( length, |i| i % 3 == 0 ) ;
199235 bencher
200236 . with_inputs ( || ( & a, & b) )
201237 . bench_values ( |( a, b) | a & b) ;
@@ -215,16 +251,16 @@ fn bitwise_and_arrow_buffer(bencher: Bencher, length: usize) {
215251/// `bitwise_and_vortex_buffer` (reference-LHS, which always allocates a result buffer).
216252#[ divan:: bench( args = INPUT_SIZE ) ]
217253fn bitand_owned_lhs_vortex_buffer ( bencher : Bencher , length : usize ) {
218- let b = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 3 == 0 ) ) ;
254+ let b = bit_buffer_from_fn ( length, |i| i % 3 == 0 ) ;
219255 bencher
220- . with_inputs ( || BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) )
256+ . with_inputs ( || bit_buffer_from_fn ( length, |i| i % 2 == 0 ) )
221257 . bench_values ( |a| a & & b) ;
222258}
223259
224260#[ divan:: bench( args = INPUT_SIZE ) ]
225261fn bitwise_or_vortex_buffer ( bencher : Bencher , length : usize ) {
226- let a = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) ;
227- let b = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 3 == 0 ) ) ;
262+ let a = bit_buffer_from_fn ( length, |i| i % 2 == 0 ) ;
263+ let b = bit_buffer_from_fn ( length, |i| i % 3 == 0 ) ;
228264 bencher
229265 . with_inputs ( || ( & a, & b) )
230266 . bench_values ( |( a, b) | a | b) ;
@@ -242,14 +278,14 @@ fn bitwise_or_arrow_buffer(bencher: Bencher, length: usize) {
242278#[ divan:: bench( args = INPUT_SIZE ) ]
243279fn bitwise_not_vortex_buffer ( bencher : Bencher , length : usize ) {
244280 bencher
245- . with_inputs ( || BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) )
281+ . with_inputs ( || bit_buffer_from_fn ( length, |i| i % 2 == 0 ) )
246282 . bench_values ( |buffer| !& buffer) ;
247283}
248284
249285#[ divan:: bench( args = INPUT_SIZE ) ]
250286fn bitwise_not_vortex_buffer_mut ( bencher : Bencher , length : usize ) {
251287 bencher
252- . with_inputs ( || BitBufferMut :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) )
288+ . with_inputs ( || bit_buffer_mut_from_fn ( length, |i| i % 2 == 0 ) )
253289 . bench_values ( |buffer| !buffer) ;
254290}
255291
@@ -262,7 +298,7 @@ fn bitwise_not_arrow_buffer(bencher: Bencher, length: usize) {
262298
263299#[ divan:: bench( args = INPUT_SIZE ) ]
264300fn iter_vortex_buffer ( bencher : Bencher , length : usize ) {
265- let buffer = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) ;
301+ let buffer = bit_buffer_from_fn ( length, |i| i % 2 == 0 ) ;
266302 bencher. with_inputs ( || & buffer) . bench_refs ( |buffer| {
267303 for value in buffer. iter ( ) {
268304 divan:: black_box ( value) ;
@@ -282,7 +318,7 @@ fn iter_arrow_buffer(bencher: Bencher, length: usize) {
282318
283319#[ divan:: bench( args = INPUT_SIZE ) ]
284320fn set_indices_vortex_buffer ( bencher : Bencher , length : usize ) {
285- let buffer = BitBuffer :: from_iter ( ( 0 .. length) . map ( |i| i % 2 == 0 ) ) ;
321+ let buffer = bit_buffer_from_fn ( length, |i| i % 2 == 0 ) ;
286322 bencher. with_inputs ( || & buffer) . bench_refs ( |buffer| {
287323 for idx in buffer. set_indices ( ) {
288324 divan:: black_box ( idx) ;
0 commit comments