diff --git a/arrow/benches/bitwise_kernel.rs b/arrow/benches/bitwise_kernel.rs index f8a1c6bec12..ae30b2610db 100644 --- a/arrow/benches/bitwise_kernel.rs +++ b/arrow/benches/bitwise_kernel.rs @@ -32,80 +32,140 @@ extern crate arrow; use arrow::util::bench_util::create_primitive_array; use arrow::util::test_util::seedable_rng; +const ARRAY_LEN: usize = 8_192; + +// These bitwise kernels are very cheap, so run them many times per Criterion iteration to +// try and reduce noise in the benchmarks. +const RUNS_PER_SAMPLE: usize = 100; + fn bitwise_array_benchmark(c: &mut Criterion) { - let size = 64 * 1024_usize; - let left_without_null = create_primitive_array::(size, 0 as f32); - let right_without_null = create_primitive_array::(size, 0 as f32); - let left_with_null = create_primitive_array::(size, 0.2_f32); - let right_with_null = create_primitive_array::(size, 0.2_f32); + let left_without_null = create_primitive_array::(ARRAY_LEN, 0 as f32); + let right_without_null = create_primitive_array::(ARRAY_LEN, 0 as f32); + let left_with_null = create_primitive_array::(ARRAY_LEN, 0.2_f32); + let right_with_null = create_primitive_array::(ARRAY_LEN, 0.2_f32); // array and let mut group = c.benchmark_group("bench bitwise array: and"); group.bench_function("bitwise array and, no nulls", |b| { - b.iter(|| hint::black_box(bitwise_and(&left_without_null, &right_without_null).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_and(&left_without_null, &right_without_null).unwrap()); + } + }) }); group.bench_function("bitwise array and, 20% nulls", |b| { - b.iter(|| hint::black_box(bitwise_and(&left_with_null, &right_with_null).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_and(&left_with_null, &right_with_null).unwrap()); + } + }) }); group.finish(); // array or let mut group = c.benchmark_group("bench bitwise: or"); group.bench_function("bitwise array or, no nulls", |b| { - b.iter(|| hint::black_box(bitwise_or(&left_without_null, &right_without_null).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_or(&left_without_null, &right_without_null).unwrap()); + } + }) }); group.bench_function("bitwise array or, 20% nulls", |b| { - b.iter(|| hint::black_box(bitwise_or(&left_with_null, &right_with_null).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_or(&left_with_null, &right_with_null).unwrap()); + } + }) }); group.finish(); // xor let mut group = c.benchmark_group("bench bitwise: xor"); group.bench_function("bitwise array xor, no nulls", |b| { - b.iter(|| hint::black_box(bitwise_xor(&left_without_null, &right_without_null).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_xor(&left_without_null, &right_without_null).unwrap()); + } + }) }); group.bench_function("bitwise array xor, 20% nulls", |b| { - b.iter(|| hint::black_box(bitwise_xor(&left_with_null, &right_with_null).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_xor(&left_with_null, &right_with_null).unwrap()); + } + }) }); group.finish(); // not let mut group = c.benchmark_group("bench bitwise: not"); group.bench_function("bitwise array not, no nulls", |b| { - b.iter(|| hint::black_box(bitwise_not(&left_without_null).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_not(&left_without_null).unwrap()); + } + }); }); group.bench_function("bitwise array not, 20% nulls", |b| { - b.iter(|| hint::black_box(bitwise_not(&left_with_null).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_not(&left_with_null).unwrap()); + } + }); }); group.finish(); } fn bitwise_array_scalar_benchmark(c: &mut Criterion) { - let size = 64 * 1024_usize; - let array_without_null = create_primitive_array::(size, 0 as f32); - let array_with_null = create_primitive_array::(size, 0.2_f32); + let array_without_null = create_primitive_array::(ARRAY_LEN, 0 as f32); + let array_with_null = create_primitive_array::(ARRAY_LEN, 0.2_f32); let scalar = seedable_rng().next_u64() as i64; // array scalar and let mut group = c.benchmark_group("bench bitwise array scalar: and"); group.bench_function("bitwise array scalar and, no nulls", |b| { - b.iter(|| hint::black_box(bitwise_and_scalar(&array_without_null, scalar).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_and_scalar(&array_without_null, scalar).unwrap()); + } + }) }); group.bench_function("bitwise array and, 20% nulls", |b| { - b.iter(|| hint::black_box(bitwise_and_scalar(&array_with_null, scalar).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_and_scalar(&array_with_null, scalar).unwrap()); + } + }) }); group.finish(); // array scalar or let mut group = c.benchmark_group("bench bitwise array scalar: or"); group.bench_function("bitwise array scalar or, no nulls", |b| { - b.iter(|| hint::black_box(bitwise_or_scalar(&array_without_null, scalar).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_or_scalar(&array_without_null, scalar).unwrap()); + } + }) }); group.bench_function("bitwise array scalar or, 20% nulls", |b| { - b.iter(|| hint::black_box(bitwise_or_scalar(&array_with_null, scalar).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_or_scalar(&array_with_null, scalar).unwrap()); + } + }) }); group.finish(); // array scalar xor let mut group = c.benchmark_group("bench bitwise array scalar: xor"); group.bench_function("bitwise array scalar xor, no nulls", |b| { - b.iter(|| hint::black_box(bitwise_xor_scalar(&array_without_null, scalar).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_xor_scalar(&array_without_null, scalar).unwrap()); + } + }) }); group.bench_function("bitwise array scalar xor, 20% nulls", |b| { - b.iter(|| hint::black_box(bitwise_xor_scalar(&array_with_null, scalar).unwrap())) + b.iter(|| { + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(bitwise_xor_scalar(&array_with_null, scalar).unwrap()); + } + }) }); group.finish(); } diff --git a/arrow/benches/boolean_kernels.rs b/arrow/benches/boolean_kernels.rs index 8d1d51242aa..9ee64cf7862 100644 --- a/arrow/benches/boolean_kernels.rs +++ b/arrow/benches/boolean_kernels.rs @@ -27,44 +27,48 @@ use arrow::array::*; use arrow::compute::kernels::boolean as boolean_kernels; use std::hint; +const ARRAY_LEN: usize = 8_192; +// These bitwise kernels are very cheap, so run them many times per Criterion iteration to +// try and reduce noise in the benchmarks. +const RUNS_PER_SAMPLE: usize = 100; + fn bench_and(lhs: &BooleanArray, rhs: &BooleanArray) { - hint::black_box(boolean_kernels::and(lhs, rhs).unwrap()); + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(boolean_kernels::and(lhs, rhs).unwrap()); + } } fn bench_or(lhs: &BooleanArray, rhs: &BooleanArray) { - hint::black_box(boolean_kernels::or(lhs, rhs).unwrap()); + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(boolean_kernels::or(lhs, rhs).unwrap()); + } } fn bench_not(array: &BooleanArray) { - hint::black_box(boolean_kernels::not(array).unwrap()); + for _ in 0..RUNS_PER_SAMPLE { + hint::black_box(boolean_kernels::not(array).unwrap()); + } } fn add_benchmark(c: &mut Criterion) { - let size = 2usize.pow(15); - let array1 = create_boolean_array(size, 0.0, 0.5); - let array2 = create_boolean_array(size, 0.0, 0.5); + let array1_full = create_boolean_array(ARRAY_LEN + 1, 0.0, 0.5); + let array2_full = create_boolean_array(ARRAY_LEN + 1, 0.0, 0.5); + let array1 = array1_full.slice(0, ARRAY_LEN); + let array2 = array2_full.slice(0, ARRAY_LEN); c.bench_function("and", |b| b.iter(|| bench_and(&array1, &array2))); c.bench_function("or", |b| b.iter(|| bench_or(&array1, &array2))); c.bench_function("not", |b| b.iter(|| bench_not(&array1))); - let array1_slice = array1.slice(1, size - 1); - let array1_slice = array1_slice - .as_any() - .downcast_ref::() - .unwrap(); - let array2_slice = array2.slice(1, size - 1); - let array2_slice = array2_slice - .as_any() - .downcast_ref::() - .unwrap(); + let array1_slice = array1_full.slice(1, ARRAY_LEN); + let array2_slice = array2_full.slice(1, ARRAY_LEN); c.bench_function("and_sliced", |b| { - b.iter(|| bench_and(array1_slice, array2_slice)) + b.iter(|| bench_and(&array1_slice, &array2_slice)) }); c.bench_function("or_sliced", |b| { - b.iter(|| bench_or(array1_slice, array2_slice)) + b.iter(|| bench_or(&array1_slice, &array2_slice)) }); - c.bench_function("not_sliced", |b| b.iter(|| bench_not(array1_slice))); + c.bench_function("not_sliced", |b| b.iter(|| bench_not(&array1_slice))); } criterion_group!(benches, add_benchmark);