This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-11412-8bdf349ae69196d757cd0f6e3df4b9651fbc445d
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git

commit 2b7cab8551afa450f8178c1bec2427399bf03668
Author: RIchard Baah <[email protected]>
AuthorDate: Wed Oct 7 01:37:32 2026 +0000

    bench(arrow-cmp): add dict_cmp benchmark (#11412)
    
    # Which issue does this PR close?
    
    N/A — split out of https://github.com/apache/arrow-rs/pull/11407
    
    # Rationale for this change
    
    `arrow-cmp` has no benchmark coverage for its dictionary comparator
    path, so the cost of `make_comparator` on `DictionaryArray`s is not
    visible in CI or local perf runs.
    
    # What changes are included in this PR?
    
    - `arrow-cmp/benches/dict_cmp.rs`; new criterion benchmark. Builds
    `Dictionary<Int32, Utf8>` arrays with 1M rows at each of 8 cardinalities
    (`10, 50, 100, 500, 750, 1000, 4000, 8192`), seeded for reproducibility.
    Each iteration constructs the comparator via `make_comparator` and
    invokes the returned closure 100 times on pseudo-random index pairs.
    
    # Are there any user-facing changes?
    
    no
---
 Cargo.lock                    |  2 ++
 arrow-cmp/Cargo.toml          |  6 ++++
 arrow-cmp/benches/dict_cmp.rs | 80 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+)

diff --git a/Cargo.lock b/Cargo.lock
index 07843eb699..a97ccd4ea5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -314,7 +314,9 @@ dependencies = [
  "arrow-array",
  "arrow-buffer",
  "arrow-schema",
+ "criterion",
  "half",
+ "rand 0.10.3",
 ]
 
 [[package]]
diff --git a/arrow-cmp/Cargo.toml b/arrow-cmp/Cargo.toml
index 9109f2b9a1..c4b00f32c7 100644
--- a/arrow-cmp/Cargo.toml
+++ b/arrow-cmp/Cargo.toml
@@ -41,6 +41,12 @@ arrow-schema = { workspace = true }
 
 [dev-dependencies]
 half = { version = "2.1", default-features = false, features = ["num-traits"] }
+criterion = { workspace = true }
+rand = { version = "0.10", default-features = false, features = ["std", 
"std_rng", "thread_rng"] }
+
+[[bench]]
+name = "dict_cmp"
+harness = false
 
 [lints]
 workspace = true
diff --git a/arrow-cmp/benches/dict_cmp.rs b/arrow-cmp/benches/dict_cmp.rs
new file mode 100644
index 0000000000..52d1f809b8
--- /dev/null
+++ b/arrow-cmp/benches/dict_cmp.rs
@@ -0,0 +1,80 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::hint::black_box;
+use std::sync::Arc;
+
+use arrow_array::types::Int32Type;
+use arrow_array::{DictionaryArray, Int32Array, StringArray};
+use arrow_cmp::make_comparator;
+use arrow_schema::SortOptions;
+use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, 
criterion_main};
+use rand::rngs::StdRng;
+use rand::{RngExt, SeedableRng};
+
+const BATCH_SIZE: usize = 8_192;
+const CALLS: usize = 100;
+const CARDINALITIES: [usize; 8] = [10, 50, 100, 500, 750, 1_000, 4_000, 8_192];
+const SEED: u64 = 0xC0FFEE;
+
+fn build_dict(rows: usize, cardinality: usize, seed: u64) -> 
DictionaryArray<Int32Type> {
+    let values: Vec<String> = (0..cardinality).map(|i| 
format!("v{i:07}")).collect();
+    let values = StringArray::from(values);
+
+    let mut rng = StdRng::seed_from_u64(seed);
+    let keys: Int32Array = (0..rows)
+        .map(|_| rng.random_range(0..cardinality) as i32)
+        .collect();
+
+    DictionaryArray::<Int32Type>::try_new(keys, Arc::new(values)).unwrap()
+}
+
+fn index_pairs(bound: usize, count: usize) -> Vec<(usize, usize)> {
+    let mut rng = StdRng::seed_from_u64(SEED.wrapping_add(0x1234));
+    (0..count)
+        .map(|_| (rng.random_range(0..bound), rng.random_range(0..bound)))
+        .collect()
+}
+
+fn bench_dict_cmp(c: &mut Criterion) {
+    let pairs = index_pairs(BATCH_SIZE, CALLS);
+
+    let mut group = c.benchmark_group("dict_cmp_utf8/100_calls_8k_batch");
+    group.throughput(Throughput::Elements(CALLS as u64));
+    group.sample_size(10);
+
+    for &card in &CARDINALITIES {
+        let left = build_dict(BATCH_SIZE, card, SEED);
+        let right = build_dict(BATCH_SIZE, card, SEED ^ 0xA5A5_A5A5);
+
+        group.bench_with_input(BenchmarkId::from_parameter(card), &card, |b, 
_| {
+            b.iter(|| {
+                let cmp = make_comparator(&left, &right, 
SortOptions::default()).unwrap();
+                let mut acc = 0i64;
+                for &(i, j) in &pairs {
+                    acc += cmp(i, j) as i64;
+                }
+                black_box(acc)
+            })
+        });
+    }
+
+    group.finish();
+}
+
+criterion_group!(benches, bench_dict_cmp);
+criterion_main!(benches);

Reply via email to