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);

Reply via email to