@@ -122,7 +122,7 @@ pub struct TopK {
122
122
/// Common sort prefix between the input and the sort expressions to allow early exit optimization
123
123
common_sort_prefix : Arc < [ PhysicalSortExpr ] > ,
124
124
/// Filter matching the state of the `TopK` heap used for dynamic filter pushdown
125
- filter : TopKDynamicFilters ,
125
+ filter : Arc < RwLock < TopKDynamicFilters > > ,
126
126
/// If true, indicates that all rows of subsequent batches are guaranteed
127
127
/// to be greater (by byte order, after row conversion) than the top K,
128
128
/// which means the top K won't change and the computation can be finished early.
@@ -134,7 +134,7 @@ pub struct TopKDynamicFilters {
134
134
/// The current *global* threshold for the dynamic filter.
135
135
/// This is shared across all partitions and is updated by any of them.
136
136
/// Stored as row bytes for efficient comparison.
137
- threshold_row : Arc < RwLock < Option < Vec < u8 > > > > ,
137
+ threshold_row : Option < Vec < u8 > > ,
138
138
/// The expression used to evaluate the dynamic filter
139
139
/// Only updated when lock held for the duration of the update
140
140
expr : Arc < DynamicFilterPhysicalExpr > ,
@@ -144,7 +144,7 @@ impl TopKDynamicFilters {
144
144
/// Create a new `TopKDynamicFilters` with the given expression
145
145
pub fn new ( expr : Arc < DynamicFilterPhysicalExpr > ) -> Self {
146
146
Self {
147
- threshold_row : Arc :: new ( RwLock :: new ( None ) ) ,
147
+ threshold_row : None ,
148
148
expr,
149
149
}
150
150
}
@@ -186,7 +186,7 @@ impl TopK {
186
186
batch_size : usize ,
187
187
runtime : Arc < RuntimeEnv > ,
188
188
metrics : & ExecutionPlanMetricsSet ,
189
- filter : TopKDynamicFilters ,
189
+ filter : Arc < RwLock < TopKDynamicFilters > > ,
190
190
) -> Result < Self > {
191
191
let reservation = MemoryConsumer :: new ( format ! ( "TopK[{partition_id}]" ) )
192
192
. register ( & runtime. memory_pool ) ;
@@ -241,7 +241,7 @@ impl TopK {
241
241
let mut selected_rows = None ;
242
242
243
243
// If a filter is provided, update it with the new rows
244
- let filter = self . filter . expr . current ( ) ?;
244
+ let filter = self . filter . read ( ) . expr . current ( ) ?;
245
245
let filtered = filter. evaluate ( & batch) ?;
246
246
let num_rows = batch. num_rows ( ) ;
247
247
let array = filtered. into_array ( num_rows) ?;
@@ -360,8 +360,8 @@ impl TopK {
360
360
// currently set in the filter with a read only lock
361
361
let needs_update = self
362
362
. filter
363
- . threshold_row
364
363
. read ( )
364
+ . threshold_row
365
365
. as_ref ( )
366
366
. map ( |current_row| {
367
367
// new < current means new threshold is more selective
@@ -380,34 +380,34 @@ impl TopK {
380
380
381
381
// update the threshold. Since there was a lock gap, we must check if it is still the best
382
382
// may have changed while we were building the expression without the lock
383
- let mut current_threshold = self . filter . threshold_row . write ( ) ;
384
- let old_threshold = current_threshold . take ( ) ;
383
+ let mut filter = self . filter . write ( ) ;
384
+ let old_threshold = filter . threshold_row . take ( ) ;
385
385
386
386
// Update filter if we successfully updated the threshold
387
387
// (or if there was no previous threshold and we're the first)
388
388
match old_threshold {
389
389
Some ( old_threshold) => {
390
390
// new threshold is still better than the old one
391
391
if new_threshold. as_slice ( ) < old_threshold. as_slice ( ) {
392
- * current_threshold = Some ( new_threshold) ;
392
+ filter . threshold_row = Some ( new_threshold) ;
393
393
} else {
394
394
// some other thread updated the threshold to a better
395
395
// one while we were building so there is no need to
396
396
// update the filter
397
- * current_threshold = Some ( old_threshold) ;
397
+ filter . threshold_row = Some ( old_threshold) ;
398
398
return Ok ( ( ) ) ;
399
399
}
400
400
}
401
401
None => {
402
402
// No previous threshold, so we can set the new one
403
- * current_threshold = Some ( new_threshold) ;
403
+ filter . threshold_row = Some ( new_threshold) ;
404
404
}
405
405
} ;
406
406
407
407
// Update the filter expression
408
408
if let Some ( pred) = predicate {
409
409
if !pred. eq ( & lit ( true ) ) {
410
- self . filter . expr . update ( pred) ?;
410
+ filter. expr . update ( pred) ?;
411
411
}
412
412
}
413
413
@@ -1141,10 +1141,9 @@ mod tests {
1141
1141
2 ,
1142
1142
runtime,
1143
1143
& metrics,
1144
- TopKDynamicFilters :: new ( Arc :: new ( DynamicFilterPhysicalExpr :: new (
1145
- vec ! [ ] ,
1146
- lit ( true ) ,
1147
- ) ) ) ,
1144
+ Arc :: new ( RwLock :: new ( TopKDynamicFilters :: new ( Arc :: new (
1145
+ DynamicFilterPhysicalExpr :: new ( vec ! [ ] , lit ( true ) ) ,
1146
+ ) ) ) ) ,
1148
1147
) ?;
1149
1148
1150
1149
// Create the first batch with two columns:
0 commit comments