diff --git a/native/spark-expr/Cargo.toml b/native/spark-expr/Cargo.toml index b5ff03444a..ea5b6fcd85 100644 --- a/native/spark-expr/Cargo.toml +++ b/native/spark-expr/Cargo.toml @@ -221,4 +221,12 @@ harness = false [[bench]] name = "cast_int_to_decimal" +harness = false + +[[bench]] +name = "levenshtein" +harness = false + +[[bench]] +name = "split" harness = false \ No newline at end of file diff --git a/native/spark-expr/benches/levenshtein.rs b/native/spark-expr/benches/levenshtein.rs new file mode 100644 index 0000000000..a3faa4da5d --- /dev/null +++ b/native/spark-expr/benches/levenshtein.rs @@ -0,0 +1,58 @@ +// 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 arrow::array::{ArrayRef, StringArray}; +use criterion::{criterion_group, criterion_main, Criterion}; +use datafusion::physical_plan::ColumnarValue; +use datafusion_comet_spark_expr::spark_levenshtein; +use std::hint::black_box; +use std::sync::Arc; + +fn create_str(rows: usize, null_every: usize, word: &str) -> ArrayRef { + let arr: StringArray = (0..rows) + .map(|i| { + if null_every != 0 && i % null_every == 0 { + None + } else { + Some(format!("{word}{}", i % 100)) + } + }) + .collect(); + Arc::new(arr) +} + +fn criterion_benchmark(c: &mut Criterion) { + let rows = 8192; + let right = create_str(rows, 0, "sitting"); + + let mut bench = |name: &str, left: &ArrayRef| { + let args = vec![ + ColumnarValue::Array(Arc::clone(left)), + ColumnarValue::Array(Arc::clone(&right)), + ]; + c.bench_function(name, |b| { + b.iter(|| black_box(spark_levenshtein(black_box(&args)).unwrap())) + }); + }; + + bench("spark_levenshtein: no nulls", &create_str(rows, 0, "kitten")); + bench("spark_levenshtein: sparse nulls", &create_str(rows, 10, "kitten")); + bench("spark_levenshtein: dense nulls", &create_str(rows, 2, "kitten")); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/native/spark-expr/benches/split.rs b/native/spark-expr/benches/split.rs new file mode 100644 index 0000000000..935f6fd2e1 --- /dev/null +++ b/native/spark-expr/benches/split.rs @@ -0,0 +1,73 @@ +// 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 arrow::array::{ArrayRef, StringArray}; +use criterion::{criterion_group, criterion_main, Criterion}; +use datafusion::common::ScalarValue; +use datafusion::physical_plan::ColumnarValue; +use datafusion_comet_spark_expr::{spark_split, spark_split_sql}; +use std::hint::black_box; +use std::sync::Arc; + +const ROWS: usize = 8192; + +fn create_csv(rows: usize, null_every: usize) -> ArrayRef { + let arr: StringArray = (0..rows) + .map(|i| { + if null_every != 0 && i % null_every == 0 { + None + } else { + Some(format!("{},{},{}", i % 100, (i + 1) % 100, (i + 2) % 100)) + } + }) + .collect(); + Arc::new(arr) +} + +fn bench_split(c: &mut Criterion) { + let pattern = ColumnarValue::Scalar(ScalarValue::Utf8(Some(",".to_string()))); + let mut bench = |name: &str, arr: &ArrayRef| { + let args = vec![ColumnarValue::Array(Arc::clone(arr)), pattern.clone()]; + c.bench_function(name, |b| { + b.iter(|| black_box(spark_split(black_box(&args)).unwrap())) + }); + }; + bench("spark_split: no nulls", &create_csv(ROWS, 0)); + bench("spark_split: sparse nulls", &create_csv(ROWS, 10)); + bench("spark_split: dense nulls", &create_csv(ROWS, 2)); +} + +fn bench_split_sql(c: &mut Criterion) { + let delimiter = ColumnarValue::Scalar(ScalarValue::Utf8(Some(",".to_string()))); + let mut bench = |name: &str, arr: &ArrayRef| { + let args = vec![ColumnarValue::Array(Arc::clone(arr)), delimiter.clone()]; + c.bench_function(name, |b| { + b.iter(|| black_box(spark_split_sql(black_box(&args)).unwrap())) + }); + }; + bench("spark_split_sql: no nulls", &create_csv(ROWS, 0)); + bench("spark_split_sql: sparse nulls", &create_csv(ROWS, 10)); + bench("spark_split_sql: dense nulls", &create_csv(ROWS, 2)); +} + +fn criterion_benchmark(c: &mut Criterion) { + bench_split(c); + bench_split_sql(c); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches);