Skip to content

Commit fde79a2

Browse files
authored
refactor: remove lifetime from DynComparator (apache#542)
This commit removes the need for an explicit lifetime on the `DynComparator`. The rationale behind this change is that callers may wish to share this comparator amongst threads and the explicit lifetime makes this harder to achieve. As a nice side-effect, performance of the sort kernel seems to have improved: ``` $ critcmp master pr group master pr ----- ------ -- bool sort 2^12 1.03 310.8±1.34µs 1.00 302.8±7.78µs bool sort nulls 2^12 1.01 287.4±2.22µs 1.00 284.0±3.23µs sort 2^10 1.04 98.7±3.58µs 1.00 94.6±0.50µs sort 2^12 1.05 510.7±5.56µs 1.00 486.2±9.94µs sort 2^12 limit 10 1.05 48.1±0.38µs 1.00 45.6±0.30µs sort 2^12 limit 100 1.04 52.8±0.37µs 1.00 50.6±0.41µs sort 2^12 limit 1000 1.06 141.1±0.94µs 1.00 132.7±0.95µs sort 2^12 limit 2^12 1.03 501.2±4.01µs 1.00 486.5±4.87µs sort nulls 2^10 1.02 70.9±0.72µs 1.00 69.4±0.51µs sort nulls 2^12 1.02 369.7±3.51µs 1.00 363.0±18.52µs sort nulls 2^12 limit 10 1.01 70.6±1.22µs 1.00 70.0±1.27µs sort nulls 2^12 limit 100 1.00 71.7±0.82µs 1.00 71.8±1.60µs sort nulls 2^12 limit 1000 1.01 80.5±1.55µs 1.00 79.4±1.41µs sort nulls 2^12 limit 2^12 1.05 375.4±4.78µs 1.00 356.1±3.04µs ```
1 parent cdcf013 commit fde79a2

File tree

2 files changed

+22
-32
lines changed

2 files changed

+22
-32
lines changed

arrow/src/array/ord.rs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::error::{ArrowError, Result};
2727
use num::Float;
2828

2929
/// Compare the values at two arbitrary indices in two arrays.
30-
pub type DynComparator<'a> = Box<dyn Fn(usize, usize) -> Ordering + 'a>;
30+
pub type DynComparator = Box<dyn Fn(usize, usize) -> Ordering + Send + Sync>;
3131

3232
/// compares two floats, placing NaNs at last
3333
fn cmp_nans_last<T: Float>(a: &T, b: &T) -> Ordering {
@@ -39,60 +39,50 @@ fn cmp_nans_last<T: Float>(a: &T, b: &T) -> Ordering {
3939
}
4040
}
4141

42-
fn compare_primitives<'a, T: ArrowPrimitiveType>(
43-
left: &'a Array,
44-
right: &'a Array,
45-
) -> DynComparator<'a>
42+
fn compare_primitives<T: ArrowPrimitiveType>(left: &Array, right: &Array) -> DynComparator
4643
where
4744
T::Native: Ord,
4845
{
49-
let left = left.as_any().downcast_ref::<PrimitiveArray<T>>().unwrap();
50-
let right = right.as_any().downcast_ref::<PrimitiveArray<T>>().unwrap();
46+
let left: PrimitiveArray<T> = PrimitiveArray::from(left.data().clone());
47+
let right: PrimitiveArray<T> = PrimitiveArray::from(right.data().clone());
5148
Box::new(move |i, j| left.value(i).cmp(&right.value(j)))
5249
}
5350

54-
fn compare_boolean<'a>(left: &'a Array, right: &'a Array) -> DynComparator<'a> {
55-
let left = left.as_any().downcast_ref::<BooleanArray>().unwrap();
56-
let right = right.as_any().downcast_ref::<BooleanArray>().unwrap();
51+
fn compare_boolean(left: &Array, right: &Array) -> DynComparator {
52+
let left: BooleanArray = BooleanArray::from(left.data().clone());
53+
let right: BooleanArray = BooleanArray::from(right.data().clone());
54+
5755
Box::new(move |i, j| left.value(i).cmp(&right.value(j)))
5856
}
5957

60-
fn compare_float<'a, T: ArrowPrimitiveType>(
61-
left: &'a Array,
62-
right: &'a Array,
63-
) -> DynComparator<'a>
58+
fn compare_float<T: ArrowPrimitiveType>(left: &Array, right: &Array) -> DynComparator
6459
where
6560
T::Native: Float,
6661
{
67-
let left = left.as_any().downcast_ref::<PrimitiveArray<T>>().unwrap();
68-
let right = right.as_any().downcast_ref::<PrimitiveArray<T>>().unwrap();
62+
let left: PrimitiveArray<T> = PrimitiveArray::from(left.data().clone());
63+
let right: PrimitiveArray<T> = PrimitiveArray::from(right.data().clone());
6964
Box::new(move |i, j| cmp_nans_last(&left.value(i), &right.value(j)))
7065
}
7166

72-
fn compare_string<'a, T>(left: &'a Array, right: &'a Array) -> DynComparator<'a>
67+
fn compare_string<T>(left: &Array, right: &Array) -> DynComparator
7368
where
7469
T: StringOffsetSizeTrait,
7570
{
76-
let left = left
77-
.as_any()
78-
.downcast_ref::<GenericStringArray<T>>()
79-
.unwrap();
80-
let right = right
81-
.as_any()
82-
.downcast_ref::<GenericStringArray<T>>()
83-
.unwrap();
71+
let left: StringArray = StringArray::from(left.data().clone());
72+
let right: StringArray = StringArray::from(right.data().clone());
73+
8474
Box::new(move |i, j| left.value(i).cmp(&right.value(j)))
8575
}
8676

87-
fn compare_dict_string<'a, T>(left: &'a Array, right: &'a Array) -> DynComparator<'a>
77+
fn compare_dict_string<T>(left: &Array, right: &Array) -> DynComparator
8878
where
8979
T: ArrowDictionaryKeyType,
9080
{
9181
let left = left.as_any().downcast_ref::<DictionaryArray<T>>().unwrap();
9282
let right = right.as_any().downcast_ref::<DictionaryArray<T>>().unwrap();
93-
let left_keys = left.keys();
94-
let right_keys = right.keys();
9583

84+
let left_keys: PrimitiveArray<T> = PrimitiveArray::from(left.keys().data().clone());
85+
let right_keys: PrimitiveArray<T> = PrimitiveArray::from(right.keys().data().clone());
9686
let left_values = StringArray::from(left.values().data().clone());
9787
let right_values = StringArray::from(right.values().data().clone());
9888

@@ -125,7 +115,7 @@ where
125115
/// ```
126116
// This is a factory of comparisons.
127117
// The lifetime 'a enforces that we cannot use the closure beyond any of the array's lifetime.
128-
pub fn build_compare<'a>(left: &'a Array, right: &'a Array) -> Result<DynComparator<'a>> {
118+
pub fn build_compare(left: &Array, right: &Array) -> Result<DynComparator> {
129119
use DataType::*;
130120
use IntervalUnit::*;
131121
use TimeUnit::*;

arrow/src/compute/kernels/sort.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -886,9 +886,9 @@ where
886886
}
887887

888888
type LexicographicalCompareItem<'a> = (
889-
&'a ArrayData, // data
890-
Box<dyn Fn(usize, usize) -> Ordering + 'a>, // comparator
891-
SortOptions, // sort_option
889+
&'a ArrayData, // data
890+
DynComparator, // comparator
891+
SortOptions, // sort_option
892892
);
893893

894894
/// A lexicographical comparator that wraps given array data (columns) and can lexicographically compare data

0 commit comments

Comments
 (0)