@@ -14,10 +14,10 @@ use crate::trace::{Batcher, Builder};
14
14
/// Creates batches from unordered tuples.
15
15
pub struct ColumnatedMergeBatcher < K , V , T , D >
16
16
where
17
- K : Columnation ,
18
- V : Columnation ,
19
- T : Columnation ,
20
- D : Columnation ,
17
+ K : Columnation + ' static ,
18
+ V : Columnation + ' static ,
19
+ T : Columnation + ' static ,
20
+ D : Columnation + ' static ,
21
21
{
22
22
sorter : MergeSorterColumnation < ( K , V ) , T , D > ,
23
23
lower : Antichain < T > ,
@@ -132,12 +132,12 @@ where
132
132
// Drain buffers (fast reclamation).
133
133
self . sorter . clear_stash ( ) ;
134
134
135
- let seal = builder. done ( self . lower . clone ( ) , upper. clone ( ) , Antichain :: from_elem ( < T as timely :: progress :: Timestamp > :: minimum ( ) ) ) ;
135
+ let seal = builder. done ( self . lower . clone ( ) , upper. clone ( ) , Antichain :: from_elem ( T :: minimum ( ) ) ) ;
136
136
self . lower = upper;
137
137
seal
138
138
}
139
139
140
- // the frontier of elements remaining after the most recent call to `self.seal`.
140
+ /// The frontier of elements remaining after the most recent call to `self.seal`.
141
141
fn frontier ( & mut self ) -> timely:: progress:: frontier:: AntichainRef < T > {
142
142
self . frontier . borrow ( )
143
143
}
@@ -184,8 +184,9 @@ impl<T: Columnation> TimelyStackQueue<T> {
184
184
}
185
185
}
186
186
187
- struct MergeSorterColumnation < D : Columnation , T : Columnation , R : Columnation > {
188
- queue : Vec < Vec < TimelyStack < ( D , T , R ) > > > , // each power-of-two length list of allocations.
187
+ struct MergeSorterColumnation < D : Columnation + ' static , T : Columnation + ' static , R : Columnation + ' static > {
188
+ /// each power-of-two length list of allocations. Do not push/pop directly but use the corresponding functions.
189
+ queue : Vec < Vec < TimelyStack < ( D , T , R ) > > > ,
189
190
stash : Vec < TimelyStack < ( D , T , R ) > > ,
190
191
pending : Vec < ( D , T , R ) > ,
191
192
logger : Option < Logger < DifferentialEvent , WorkerIdentifier > > ,
@@ -223,29 +224,6 @@ impl<D: Ord+Columnation+'static, T: Ord+Columnation+'static, R: Semigroup+Column
223
224
}
224
225
}
225
226
226
- /// Account size changes. Only performs work if a logger exists.
227
- ///
228
- /// Calculate the size based on the [`TimelyStack`]s passed along, with each attribute
229
- /// multiplied by `diff`. Usually, one wants to pass 1 or -1 as the diff.
230
- fn account < ' a , I : IntoIterator < Item =& ' a TimelyStack < ( D , T , R ) > > > ( & self , items : I , diff : isize ) {
231
- if let Some ( logger) = & self . logger {
232
- let ( mut siz, mut capacity, mut allocations) = ( 0isize , 0isize , 0isize ) ;
233
- for stack in items {
234
- stack. heap_size ( |s, c| {
235
- siz = siz. saturating_add_unsigned ( s) ;
236
- capacity = capacity. saturating_add_unsigned ( c) ;
237
- allocations += isize:: from ( c > 0 ) ;
238
- } ) ;
239
- }
240
- logger. log ( BatcherEvent {
241
- operator : self . operator_id ,
242
- size_diff : siz * diff,
243
- capacity_diff : capacity * diff,
244
- allocations_diff : allocations * diff,
245
- } )
246
- }
247
- }
248
-
249
227
fn empty ( & mut self ) -> TimelyStack < ( D , T , R ) > {
250
228
self . stash . pop ( ) . unwrap_or_else ( || TimelyStack :: with_capacity ( Self :: buffer_size ( ) ) )
251
229
}
@@ -290,14 +268,12 @@ impl<D: Ord+Columnation+'static, T: Ord+Columnation+'static, R: Semigroup+Column
290
268
for tuple in self . pending . drain ( ..) {
291
269
stack. copy ( & tuple) ;
292
270
}
293
- self . account ( [ & stack] , 1 ) ;
294
- self . queue . push ( vec ! [ stack] ) ;
271
+ self . queue_push ( vec ! [ stack] ) ;
295
272
while self . queue . len ( ) > 1 && ( self . queue [ self . queue . len ( ) -1 ] . len ( ) >= self . queue [ self . queue . len ( ) -2 ] . len ( ) / 2 ) {
296
- let list1 = self . queue . pop ( ) . unwrap ( ) ;
297
- let list2 = self . queue . pop ( ) . unwrap ( ) ;
273
+ let list1 = self . queue_pop ( ) . unwrap ( ) ;
274
+ let list2 = self . queue_pop ( ) . unwrap ( ) ;
298
275
let merged = self . merge_by ( list1, list2) ;
299
- self . account ( & merged, 1 ) ;
300
- self . queue . push ( merged) ;
276
+ self . queue_push ( merged) ;
301
277
}
302
278
}
303
279
}
@@ -306,34 +282,31 @@ impl<D: Ord+Columnation+'static, T: Ord+Columnation+'static, R: Semigroup+Column
306
282
// to break it down to be so.
307
283
fn push_list ( & mut self , list : Vec < TimelyStack < ( D , T , R ) > > ) {
308
284
while self . queue . len ( ) > 1 && self . queue [ self . queue . len ( ) -1 ] . len ( ) < list. len ( ) {
309
- let list1 = self . queue . pop ( ) . unwrap ( ) ;
310
- let list2 = self . queue . pop ( ) . unwrap ( ) ;
285
+ let list1 = self . queue_pop ( ) . unwrap ( ) ;
286
+ let list2 = self . queue_pop ( ) . unwrap ( ) ;
311
287
let merged = self . merge_by ( list1, list2) ;
312
- self . account ( & merged, 1 ) ;
313
- self . queue . push ( merged) ;
288
+ self . queue_push ( merged) ;
314
289
}
315
- self . queue . push ( list) ;
290
+ self . queue_push ( list) ;
316
291
}
317
292
318
293
fn finish_into ( & mut self , target : & mut Vec < TimelyStack < ( D , T , R ) > > ) {
319
294
crate :: consolidation:: consolidate_updates ( & mut self . pending ) ;
320
295
self . flush_pending ( ) ;
321
296
while self . queue . len ( ) > 1 {
322
- let list1 = self . queue . pop ( ) . unwrap ( ) ;
323
- let list2 = self . queue . pop ( ) . unwrap ( ) ;
297
+ let list1 = self . queue_pop ( ) . unwrap ( ) ;
298
+ let list2 = self . queue_pop ( ) . unwrap ( ) ;
324
299
let merged = self . merge_by ( list1, list2) ;
325
- self . queue . push ( merged) ;
300
+ self . queue_push ( merged) ;
326
301
}
327
302
328
- if let Some ( mut last) = self . queue . pop ( ) {
303
+ if let Some ( mut last) = self . queue_pop ( ) {
329
304
std:: mem:: swap ( & mut last, target) ;
330
305
}
331
306
}
332
307
333
308
// merges two sorted input lists into one sorted output list.
334
309
fn merge_by ( & mut self , list1 : Vec < TimelyStack < ( D , T , R ) > > , list2 : Vec < TimelyStack < ( D , T , R ) > > ) -> Vec < TimelyStack < ( D , T , R ) > > {
335
- self . account ( list1. iter ( ) . chain ( list2. iter ( ) ) , -1 ) ;
336
-
337
310
use std:: cmp:: Ordering ;
338
311
339
312
// TODO: `list1` and `list2` get dropped; would be better to reuse?
@@ -411,3 +384,52 @@ impl<D: Ord+Columnation+'static, T: Ord+Columnation+'static, R: Semigroup+Column
411
384
output
412
385
}
413
386
}
387
+
388
+ impl < D : Columnation + ' static , T : Columnation + ' static , R : Columnation + ' static > MergeSorterColumnation < D , T , R > {
389
+ /// Pop a batch from `self.queue` and account size changes.
390
+ #[ inline]
391
+ fn queue_pop ( & mut self ) -> Option < Vec < TimelyStack < ( D , T , R ) > > > {
392
+ let batch = self . queue . pop ( ) ;
393
+ self . account ( batch. iter ( ) . flatten ( ) , -1 ) ;
394
+ batch
395
+ }
396
+
397
+ /// Push a batch to `self.queue` and account size changes.
398
+ #[ inline]
399
+ fn queue_push ( & mut self , batch : Vec < TimelyStack < ( D , T , R ) > > ) {
400
+ self . account ( & batch, 1 ) ;
401
+ self . queue . push ( batch) ;
402
+ }
403
+
404
+ /// Account size changes. Only performs work if a logger exists.
405
+ ///
406
+ /// Calculate the size based on the [`TimelyStack`]s passed along, with each attribute
407
+ /// multiplied by `diff`. Usually, one wants to pass 1 or -1 as the diff.
408
+ fn account < ' a , I : IntoIterator < Item =& ' a TimelyStack < ( D , T , R ) > > > ( & self , items : I , diff : isize ) {
409
+ if let Some ( logger) = & self . logger {
410
+ let ( mut records, mut siz, mut capacity, mut allocations) = ( 0isize , 0isize , 0isize , 0isize ) ;
411
+ for stack in items {
412
+ records = records. saturating_add_unsigned ( stack. len ( ) ) ;
413
+ stack. heap_size ( |s, c| {
414
+ siz = siz. saturating_add_unsigned ( s) ;
415
+ capacity = capacity. saturating_add_unsigned ( c) ;
416
+ allocations += isize:: from ( c > 0 ) ;
417
+ } ) ;
418
+ }
419
+ logger. log ( BatcherEvent {
420
+ operator : self . operator_id ,
421
+ records_diff : records * diff,
422
+ size_diff : siz * diff,
423
+ capacity_diff : capacity * diff,
424
+ allocations_diff : allocations * diff,
425
+ } )
426
+ }
427
+ }
428
+
429
+ }
430
+
431
+ impl < D : Columnation + ' static , T : Columnation + ' static , R : Columnation + ' static > Drop for MergeSorterColumnation < D , T , R > {
432
+ fn drop ( & mut self ) {
433
+ while self . queue_pop ( ) . is_some ( ) { }
434
+ }
435
+ }
0 commit comments