Skip to content

Commit dcf4864

Browse files
committed
perf
1 parent 7758889 commit dcf4864

File tree

1 file changed

+38
-18
lines changed

1 file changed

+38
-18
lines changed

arrow-select/src/coalesce/primitive.rs

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -113,66 +113,86 @@ impl<T: ArrowPrimitiveType + Debug> InProgressArray for InProgressPrimitiveArray
113113
// Use the predicate's strategy for optimal iteration
114114
match filter.strategy() {
115115
IterationStrategy::SlicesIterator => {
116-
// Copy values using slices
117-
for (start, end) in SlicesIterator::new(filter.filter_array()) {
118-
self.current.extend_from_slice(&values[start..end]);
119-
}
120-
// Copy nulls using slices
116+
// Copy values, nulls using slices
121117
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
122118
for (start, end) in SlicesIterator::new(filter.filter_array()) {
119+
// SAFETY: slices are derived from filter predicate
120+
self.current
121+
.extend_from_slice(unsafe { values.get_unchecked(start..end) });
123122
let slice = nulls.slice(start, end - start);
124123
self.nulls.append_buffer(&slice);
125124
}
126125
} else {
126+
for (start, end) in SlicesIterator::new(filter.filter_array()) {
127+
// SAFETY: SlicesIterator produces valid ranges derived from filter
128+
self.current
129+
.extend_from_slice(unsafe { values.get_unchecked(start..end) });
130+
}
127131
self.nulls.append_n_non_nulls(count);
128132
}
129133
}
130134
IterationStrategy::Slices(slices) => {
131-
// Copy values using precomputed slices
132-
for &(start, end) in slices {
133-
self.current.extend_from_slice(&values[start..end]);
134-
}
135-
// Copy nulls using slices
135+
// Copy values and nulls using precomputed slices - single iteration
136136
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
137137
for &(start, end) in slices {
138+
// SAFETY: slices are derived from filter predicate
139+
self.current
140+
.extend_from_slice(unsafe { values.get_unchecked(start..end) });
138141
let slice = nulls.slice(start, end - start);
139142
self.nulls.append_buffer(&slice);
140143
}
141144
} else {
145+
for &(start, end) in slices {
146+
// SAFETY: slices are derived from filter predicate
147+
self.current
148+
.extend_from_slice(unsafe { values.get_unchecked(start..end) });
149+
}
142150
self.nulls.append_n_non_nulls(count);
143151
}
144152
}
145153
IterationStrategy::IndexIterator => {
146154
// Copy values and nulls for each index
147155
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
148-
for idx in IndexIterator::new(filter.filter_array(), count) {
156+
let indices = IndexIterator::new(filter.filter_array(), count);
157+
self.current.extend(indices.map(|idx: usize| {
149158
if nulls.is_null(idx) {
150159
self.nulls.append_null();
151160
} else {
152161
self.nulls.append_non_null();
153162
}
154-
self.current.push(values[idx]);
155-
}
163+
// SAFETY: idx is derived from filter predicate
164+
unsafe { *values.get_unchecked(idx) }
165+
}));
156166
} else {
157167
self.nulls.append_n_non_nulls(count);
158168
let indices = IndexIterator::new(filter.filter_array(), count);
159-
self.current.extend(indices.map(|idx| values[idx]));
169+
// SAFETY: indices are derived from filter predicate
170+
self.current
171+
.extend(indices.map(|idx: usize| unsafe { *values.get_unchecked(idx) }));
160172
}
161173
}
162174
IterationStrategy::Indices(indices) => {
163175
// Copy values and nulls using precomputed indices
164176
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
165-
for &idx in indices {
177+
self.current.extend(indices.iter().map(|&idx| {
178+
// TODO: speed up
166179
if nulls.is_null(idx) {
167180
self.nulls.append_null();
168181
} else {
169182
self.nulls.append_non_null();
170183
}
171-
}
184+
// SAFETY: indices are derived from filter predicate
185+
unsafe { *values.get_unchecked(idx) }
186+
}));
172187
} else {
173188
self.nulls.append_n_non_nulls(count);
174-
}
175-
self.current.extend(indices.iter().map(|&idx| values[idx]));
189+
// SAFETY: indices are derived from filter predicate
190+
self.current.extend(
191+
indices
192+
.iter()
193+
.map(|&idx| unsafe { *values.get_unchecked(idx) }),
194+
)
195+
};
176196
}
177197
IterationStrategy::All => {
178198
// Copy all values

0 commit comments

Comments
 (0)