4444//! | Utf8View length-12 cases | Utf8View | 12-byte strings | 16, 64 |
4545//! | Utf8View long-string cases | Utf8View | 24-byte strings | 4, 16, 64, 256 |
4646//! | Shared-prefix string cases | Utf8, Utf8View | same prefix, different suffix | 16, 32, 64 |
47- //! | Fixed-size binary cases | FixedSizeBinary(16) | fixed-width binary values | 4 , 64, 256, 10000 |
47+ //! | Fixed-size binary cases | FixedSizeBinary(1, 2, 16) | fixed-width binary values | 16 (1 byte) , 64 (2 bytes), 4/64/256/ 10000 (16 bytes) |
4848
4949use arrow:: array:: types:: IntervalMonthDayNano ;
5050use arrow:: array:: * ;
5151use arrow:: datatypes:: { Field , Int32Type , IntervalMonthDayNanoType , Schema } ;
5252use arrow:: record_batch:: RecordBatch ;
5353use criterion:: { BenchmarkId , Criterion , criterion_group, criterion_main} ;
54- use datafusion_common:: ScalarValue ;
54+ use datafusion_common:: { HashSet , ScalarValue } ;
5555use datafusion_physical_expr:: expressions:: { col, in_list, lit} ;
5656use half:: f16;
5757use rand:: distr:: Alphanumeric ;
@@ -996,40 +996,51 @@ fn bench_nulls(c: &mut Criterion) {
996996}
997997
998998// =============================================================================
999- // FIXED SIZE BINARY BENCHMARKS (FixedSizeBinary<16>, e.g. UUIDs)
999+ // FIXED SIZE BINARY BENCHMARKS
10001000// =============================================================================
10011001
1002- /// Generates a random 16-byte value (UUID-sized).
1003- fn random_fixed_binary_16 ( rng : & mut StdRng ) -> Vec < u8 > {
1004- let mut buf = vec ! [ 0u8 ; 16 ] ;
1002+ fn random_fixed_binary ( rng : & mut StdRng , width : i32 ) -> Vec < u8 > {
1003+ let mut buf = vec ! [ 0u8 ; width as usize ] ;
10051004 rng. fill ( & mut buf[ ..] ) ;
10061005 buf
10071006}
10081007
1009- /// Benchmarks FixedSizeBinary(16) IN list evaluation.
10101008/// FixedSizeBinary doesn't use the generic numeric helpers since its array
10111009/// construction differs from primitive types.
10121010fn bench_fixed_size_binary_inner (
10131011 c : & mut Criterion ,
1014- name : & str ,
1012+ width : i32 ,
10151013 list_size : usize ,
10161014 match_rate : f64 ,
10171015) {
1018- let seed = 0xF1ED_B1A7_u64 . wrapping_add ( list_size as u64 * 0x6666 ) ;
1016+ let seed = 0xF1ED_B1A7_u64
1017+ . wrapping_add ( list_size as u64 * 0x6666 )
1018+ . wrapping_add ( width as u64 * 0x7777 ) ;
10191019 let mut rng = StdRng :: seed_from_u64 ( seed) ;
10201020
1021- // Generate IN list values (16-byte each)
1022- let haystack: Vec < Vec < u8 > > = ( 0 ..list_size)
1023- . map ( |_| random_fixed_binary_16 ( & mut rng) )
1024- . collect ( ) ;
1021+ // Keep the haystack unique so each configured list size reaches the
1022+ // intended filter strategy.
1023+ let mut haystack_set = HashSet :: with_capacity ( list_size) ;
1024+ let mut haystack = Vec :: with_capacity ( list_size) ;
1025+ while haystack. len ( ) < list_size {
1026+ let value = random_fixed_binary ( & mut rng, width) ;
1027+ if haystack_set. insert ( value. clone ( ) ) {
1028+ haystack. push ( value) ;
1029+ }
1030+ }
10251031
10261032 // Generate array with controlled match rate
10271033 let values: Vec < Vec < u8 > > = ( 0 ..ARRAY_SIZE )
10281034 . map ( |_| {
10291035 if !haystack. is_empty ( ) && rng. random_bool ( match_rate) {
10301036 haystack. choose ( & mut rng) . unwrap ( ) . clone ( )
10311037 } else {
1032- random_fixed_binary_16 ( & mut rng)
1038+ loop {
1039+ let value = random_fixed_binary ( & mut rng, width) ;
1040+ if !haystack_set. contains ( & value) {
1041+ break value;
1042+ }
1043+ }
10331044 }
10341045 } )
10351046 . collect ( ) ;
@@ -1040,28 +1051,28 @@ fn bench_fixed_size_binary_inner(
10401051 let schema = Schema :: new ( vec ! [ Field :: new( "a" , array. data_type( ) . clone( ) , true ) ] ) ;
10411052 let exprs: Vec < _ > = haystack
10421053 . iter ( )
1043- . map ( |v| lit ( ScalarValue :: FixedSizeBinary ( 16 , Some ( v. clone ( ) ) ) ) )
1054+ . map ( |v| lit ( ScalarValue :: FixedSizeBinary ( width , Some ( v. clone ( ) ) ) ) )
10441055 . collect ( ) ;
10451056 let expr = in_list ( col ( "a" , & schema) . unwrap ( ) , exprs, & false , & schema) . unwrap ( ) ;
10461057 let batch = RecordBatch :: try_new ( Arc :: new ( schema) , vec ! [ Arc :: new( array) as ArrayRef ] )
10471058 . unwrap ( ) ;
10481059
10491060 c. bench_with_input (
1050- BenchmarkId :: new ( "fixed_size_binary" , name) ,
1061+ BenchmarkId :: new (
1062+ "fixed_size_binary" ,
1063+ format ! ( "fsb{width}/list={list_size}/match={}%" , match_rate * 100.0 ) ,
1064+ ) ,
10511065 & batch,
10521066 |b, batch| b. iter ( || expr. evaluate ( batch) . unwrap ( ) ) ,
10531067 ) ;
10541068}
10551069
10561070fn bench_fixed_size_binary ( c : & mut Criterion ) {
1057- for list_size in [ 4 , 64 , 256 , 10000 ] {
1071+ for ( width, list_size) in
1072+ [ ( 1 , 16 ) , ( 2 , 64 ) , ( 16 , 4 ) , ( 16 , 64 ) , ( 16 , 256 ) , ( 16 , 10000 ) ]
1073+ {
10581074 for match_pct in MATCH_RATES {
1059- bench_fixed_size_binary_inner (
1060- c,
1061- & format ! ( "fsb16/list={list_size}/match={match_pct}%" ) ,
1062- list_size,
1063- match_pct as f64 / 100.0 ,
1064- ) ;
1075+ bench_fixed_size_binary_inner ( c, width, list_size, match_pct as f64 / 100.0 ) ;
10651076 }
10661077 }
10671078}
0 commit comments