This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 29ec1c09fa Add Variant integer-to-decimal and float-to-decimal
benchmarks (#11416)
29ec1c09fa is described below
commit 29ec1c09fa6c8454848b596f95eafcf36662fc87
Author: Kosta Tarasov <[email protected]>
AuthorDate: Wed Oct 7 01:51:42 2026 +0000
Add Variant integer-to-decimal and float-to-decimal benchmarks (#11416)
# Which issue does this PR close?
- Relates to #10795 and #11309.
- Adds Variant benchmark coverage for #11302 and the integer conversion
fix tracked in #11309.
# Rationale for this change
The existing `variant_get` benchmarks do not cover integer or
floating-point conversion to decimals. These cases provide a baseline
for measuring changes to precision validation and scaling behavior.
# What changes are included in this PR?
Add 16 cases covering successful safe/strict conversions, scaling,
Decimal256 output, precision overflow, and non-finite floating-point
inputs.
Fixtures contain 8,192 unshredded Variant rows with approximately 10%
nulls and a fixed RNG seed. They reuse the existing benchmark helper,
with fixture construction outside timing.
Float precision-overflow cases run before and after #11302, although
their outputs differ: the fix replaces out-of-precision values with
nulls.
# Are these changes tested?
This PR adds benchmarks only. All 16 cases were smoke-tested and
measured against #11302 and its base. No library behavior changes or
additional unit tests are included.
# Are there any significant user-facing changes?
No.
# AI usage
Developed with assistance from OpenAI Codex for implementation,
validation, and this description.
---
parquet-variant-compute/benches/variant_kernels.rs | 147 +++++++++++++++++++++
1 file changed, 147 insertions(+)
diff --git a/parquet-variant-compute/benches/variant_kernels.rs
b/parquet-variant-compute/benches/variant_kernels.rs
index 0d35d68901..95bd73e766 100644
--- a/parquet-variant-compute/benches/variant_kernels.rs
+++ b/parquet-variant-compute/benches/variant_kernels.rs
@@ -19,6 +19,7 @@ use arrow::array::{
Array, ArrayRef, BinaryViewArray, BinaryViewBuilder, Int32Array,
StringArray, StructArray,
};
use arrow::buffer::Buffer;
+use arrow::compute::CastOptions;
use arrow_schema::{DataType, Field, FieldRef, Fields};
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime};
use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
@@ -520,6 +521,150 @@ pub fn variant_get_binary_from_string_bench(c: &mut
Criterion) {
);
}
+pub fn variant_get_decimal_from_int_bench(c: &mut Criterion) {
+ let int32 = |rng: &mut StdRng|
Variant::Int32(rng.random_range(-1_000_000..1_000_000));
+ let int64 = |rng: &mut StdRng|
Variant::Int64(rng.random_range(-1_000_000..1_000_000));
+ bench_variant_get_decimal(
+ c,
+ "int32_to_decimal32(9,0)_valid",
+ int32,
+ DataType::Decimal32(9, 0),
+ &[true, false],
+ );
+ bench_variant_get_decimal(
+ c,
+ "int64_to_decimal128(38,2)_scale_up",
+ int64,
+ DataType::Decimal128(38, 2),
+ &[true, false],
+ );
+ bench_variant_get_decimal(
+ c,
+ "int64_to_decimal256(76,-1)_scale_down",
+ int64,
+ DataType::Decimal256(76, -1),
+ &[true],
+ );
+ bench_variant_get_decimal(
+ c,
+ "int64_to_decimal32(9,-20)_all_zero",
+ int64,
+ DataType::Decimal32(9, -20),
+ &[true],
+ );
+
+ let wide = |rng: &mut StdRng|
Variant::Int64(rng.random_range(5_000_000_000..5_000_100_000));
+ bench_variant_get_decimal(
+ c,
+ "int64_to_decimal32(9,-1)_scale_before_narrowing",
+ wide,
+ DataType::Decimal32(9, -1),
+ &[true],
+ );
+ let overflow = |rng: &mut StdRng|
Variant::Int32(rng.random_range(100_000_000..1_000_000_000));
+ bench_variant_get_decimal(
+ c,
+ "int32_to_decimal32(8,0)_precision_overflow",
+ overflow,
+ DataType::Decimal32(8, 0),
+ &[true],
+ );
+}
+
+pub fn variant_get_decimal_from_float_bench(c: &mut Criterion) {
+ let float = |rng: &mut StdRng|
Variant::Float(rng.random_range(-9999.0..9999.0));
+ let double = |rng: &mut StdRng|
Variant::Double(rng.random_range(-9999.0..9999.0));
+ bench_variant_get_decimal(
+ c,
+ "float_to_decimal32(7,2)_valid",
+ float,
+ DataType::Decimal32(7, 2),
+ &[true, false],
+ );
+ bench_variant_get_decimal(
+ c,
+ "double_to_decimal128(20,3)_valid",
+ double,
+ DataType::Decimal128(20, 3),
+ &[true, false],
+ );
+ bench_variant_get_decimal(
+ c,
+ "double_to_decimal256(40,-2)_scale_down",
+ double,
+ DataType::Decimal256(40, -2),
+ &[true],
+ );
+
+ // Include direct and rounding-induced precision overflow for both source
types.
+ // Before #11302 these return out-of-precision values instead of nulls.
Keep
+ // the fixture usable on both revisions so the cost of the fix can be
measured.
+ let samples = [1000.0, -1000.0, 999.75, -999.75];
+ bench_variant_get_decimal(
+ c,
+ "float_to_decimal64(3,0)_precision_overflow",
+ |rng| Variant::Float(samples[rng.random_range(0..samples.len())] as
f32),
+ DataType::Decimal64(3, 0),
+ &[true],
+ );
+ bench_variant_get_decimal(
+ c,
+ "double_to_decimal64(3,0)_precision_overflow",
+ |rng| Variant::Double(samples[rng.random_range(0..samples.len())]),
+ DataType::Decimal64(3, 0),
+ &[true],
+ );
+
+ let samples = [f64::NAN, f64::INFINITY, f64::NEG_INFINITY];
+ bench_variant_get_decimal(
+ c,
+ "double_to_decimal128(20,3)_non_finite",
+ |rng| Variant::Double(samples[rng.random_range(0..samples.len())]),
+ DataType::Decimal128(20, 3),
+ &[true],
+ );
+}
+
+fn bench_variant_get_decimal(
+ c: &mut Criterion,
+ name: &str,
+ value: impl Fn(&mut StdRng) -> Variant<'static, 'static>,
+ target: DataType,
+ modes: &[bool],
+) {
+ for &safe in modes {
+ let options = GetOptions::new()
+ .with_as_type(Some(Arc::new(Field::new(
+ "typed_value",
+ target.clone(),
+ true,
+ ))))
+ .with_cast_options(CastOptions {
+ safe,
+ ..Default::default()
+ });
+ let mode = if safe { "safe" } else { "strict" };
+ bench_variant_get(
+ c,
+ &format!("variant_get_decimal_{name}_8192_{mode}"),
+ |rng, array_size| {
+ // Unshredded input exercises Variant's scalar conversion. Keep
+ // the requested numeric type and make every tenth row null.
+ let mut builder = VariantArrayBuilder::new(array_size);
+ for i in 0..array_size {
+ if i % 10 == 0 {
+ builder.append_null();
+ } else {
+ builder.append_variant(value(rng));
+ }
+ }
+ builder.build()
+ },
+ options,
+ );
+ }
+}
+
criterion_group!(
benches,
variant_get_bench,
@@ -543,6 +688,8 @@ criterion_group!(
variant_get_utf8_from_list_bench,
variant_get_utf8_from_map_in_list_bench,
variant_get_binary_from_string_bench,
+ variant_get_decimal_from_int_bench,
+ variant_get_decimal_from_float_bench,
);
criterion_main!(benches);