Skip to content

Commit b6cccfe

Browse files
Add FixedSizeBinary IN LIST benchmarks
1 parent 426b351 commit b6cccfe

1 file changed

Lines changed: 34 additions & 23 deletions

File tree

datafusion/physical-expr/benches/in_list_strategy.rs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@
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
4949
use arrow::array::types::IntervalMonthDayNano;
5050
use arrow::array::*;
5151
use arrow::datatypes::{Field, Int32Type, IntervalMonthDayNanoType, Schema};
5252
use arrow::record_batch::RecordBatch;
5353
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
54-
use datafusion_common::ScalarValue;
54+
use datafusion_common::{HashSet, ScalarValue};
5555
use datafusion_physical_expr::expressions::{col, in_list, lit};
5656
use half::f16;
5757
use 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.
10121010
fn 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

10561070
fn 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

Comments
 (0)