75
75
use std:: collections:: { BinaryHeap , HashMap , VecDeque } ;
76
76
use std:: cmp:: Reverse ;
77
77
78
+ use columnar:: { Columnar , Len , Index } ;
79
+ use columnar:: ColumnVec ;
80
+
78
81
use crate :: progress:: Timestamp ;
79
82
use crate :: progress:: { Source , Target } ;
80
83
use crate :: progress:: ChangeBatch ;
@@ -84,6 +87,62 @@ use crate::progress::frontier::{Antichain, MutableAntichain};
84
87
use crate :: progress:: timestamp:: PathSummary ;
85
88
86
89
90
+ use vec_antichain:: VecAntichain ;
91
+
92
+ /// A stand-in for `Vec<Antichain<T>>`.
93
+ mod vec_antichain {
94
+
95
+ use columnar:: { Columnar , Len , Index , IndexMut } ;
96
+ use columnar:: { ColumnVec , Slice } ;
97
+
98
+ use crate :: progress:: Antichain ;
99
+
100
+ #[ derive( Clone , Debug ) ]
101
+ pub struct VecAntichain < T > ( ColumnVec < T > ) ;
102
+
103
+ impl < TC : Default > Default for VecAntichain < TC > {
104
+ fn default ( ) -> Self {
105
+ Self ( Default :: default ( ) )
106
+ }
107
+ }
108
+
109
+ impl < TC > Len for VecAntichain < TC > {
110
+ #[ inline( always) ] fn len ( & self ) -> usize { self . 0 . len ( ) }
111
+ }
112
+
113
+ impl < TC > Index for VecAntichain < TC > {
114
+ type Index < ' a > = Slice < & ' a TC > where TC : ' a ;
115
+
116
+ #[ inline( always) ]
117
+ fn index ( & self , index : usize ) -> Self :: Index < ' _ > {
118
+ self . 0 . index ( index)
119
+ }
120
+ }
121
+ impl < TC > IndexMut for VecAntichain < TC > {
122
+ type IndexMut < ' a > = Slice < & ' a mut TC > where TC : ' a ;
123
+
124
+ #[ inline( always) ]
125
+ fn index_mut ( & mut self , index : usize ) -> Self :: IndexMut < ' _ > {
126
+ self . 0 . index_mut ( index)
127
+ }
128
+ }
129
+
130
+ impl < T , TC : Columnar < T > > Columnar < Antichain < T > > for VecAntichain < TC > {
131
+ #[ inline( always) ]
132
+ fn copy ( & mut self , item : & Antichain < T > ) {
133
+ self . 0 . copy ( item. elements ( ) ) ;
134
+ }
135
+ fn clear ( & mut self ) {
136
+ unimplemented ! ( )
137
+ }
138
+ fn heap_size ( & self ) -> ( usize , usize ) {
139
+ unimplemented ! ( )
140
+ }
141
+ }
142
+ }
143
+
144
+
145
+
87
146
/// A topology builder, which can summarize reachability along paths.
88
147
///
89
148
/// A `Builder` takes descriptions of the nodes and edges in a graph, and compiles
@@ -132,43 +191,42 @@ pub struct Builder<T: Timestamp> {
132
191
/// Indexed by operator index, then input port, then output port. This is the
133
192
/// same format returned by `get_internal_summary`, as if we simply appended
134
193
/// all of the summaries for the hosted nodes.
135
- pub nodes : Vec < Vec < Vec < Antichain < T :: Summary > > > > ,
194
+ nodes : ColumnVec < ColumnVec < VecAntichain < Vec < T :: Summary > > > > ,
136
195
/// Direct connections from sources to targets.
137
196
///
138
197
/// Edges do not affect timestamps, so we only need to know the connectivity.
139
198
/// Indexed by operator index then output port.
140
- pub edges : Vec < Vec < Vec < Target > > > ,
199
+ edges : Vec < Vec < Vec < Target > > > ,
141
200
/// Numbers of inputs and outputs for each node.
142
- pub shape : Vec < ( usize , usize ) > ,
201
+ shape : Vec < ( usize , usize ) > ,
143
202
}
144
203
145
204
impl < T : Timestamp > Builder < T > {
146
205
147
206
/// Create a new empty topology builder.
148
207
pub fn new ( ) -> Self {
149
208
Builder {
150
- nodes : Vec :: new ( ) ,
209
+ nodes : Default :: default ( ) ,
151
210
edges : Vec :: new ( ) ,
152
211
shape : Vec :: new ( ) ,
153
212
}
154
213
}
155
214
156
215
/// Add links internal to operators.
157
216
///
158
- /// This method overwrites any existing summary, instead of anything more sophisticated .
217
+ /// Nodes must be added in strictly increasing order of `index` .
159
218
pub fn add_node ( & mut self , index : usize , inputs : usize , outputs : usize , summary : Vec < Vec < Antichain < T :: Summary > > > ) {
160
219
161
220
// Assert that all summaries exist.
162
221
debug_assert_eq ! ( inputs, summary. len( ) ) ;
163
222
for x in summary. iter ( ) { debug_assert_eq ! ( outputs, x. len( ) ) ; }
164
223
165
- while self . nodes . len ( ) <= index {
166
- self . nodes . push ( Vec :: new ( ) ) ;
167
- self . edges . push ( Vec :: new ( ) ) ;
168
- self . shape . push ( ( 0 , 0 ) ) ;
169
- }
224
+ assert_eq ! ( self . nodes. len( ) , index) ;
225
+
226
+ self . nodes . push ( summary ) ;
227
+ self . edges . push ( Vec :: new ( ) ) ;
228
+ self . shape . push ( ( 0 , 0 ) ) ;
170
229
171
- self . nodes [ index] = summary;
172
230
if self . edges [ index] . len ( ) != outputs {
173
231
self . edges [ index] = vec ! [ Vec :: new( ) ; outputs] ;
174
232
}
@@ -287,7 +345,7 @@ impl<T: Timestamp> Builder<T> {
287
345
in_degree. entry ( target) . or_insert ( 0 ) ;
288
346
for ( output, summaries) in outputs. iter ( ) . enumerate ( ) {
289
347
let source = Location :: new_source ( index, output) ;
290
- for summary in summaries. elements ( ) . iter ( ) {
348
+ for summary in summaries. iter ( ) {
291
349
if summary == & Default :: default ( ) {
292
350
* in_degree. entry ( source) . or_insert ( 0 ) += 1 ;
293
351
}
@@ -322,9 +380,9 @@ impl<T: Timestamp> Builder<T> {
322
380
}
323
381
} ,
324
382
Port :: Target ( port) => {
325
- for ( output, summaries) in self . nodes [ node] [ port] . iter ( ) . enumerate ( ) {
383
+ for ( output, summaries) in self . nodes . index ( node) . index ( port) . iter ( ) . enumerate ( ) {
326
384
let source = Location :: new_source ( node, output) ;
327
- for summary in summaries. elements ( ) . iter ( ) {
385
+ for summary in summaries. iter ( ) {
328
386
if summary == & Default :: default ( ) {
329
387
* in_degree. get_mut ( & source) . unwrap ( ) -= 1 ;
330
388
if in_degree[ & source] == 0 {
@@ -361,12 +419,12 @@ pub struct Tracker<T:Timestamp> {
361
419
/// Indexed by operator index, then input port, then output port. This is the
362
420
/// same format returned by `get_internal_summary`, as if we simply appended
363
421
/// all of the summaries for the hosted nodes.
364
- nodes : Vec < Vec < Vec < Antichain < T :: Summary > > > > ,
422
+ nodes : ColumnVec < ColumnVec < VecAntichain < Vec < T :: Summary > > > > ,
365
423
/// Direct connections from sources to targets.
366
424
///
367
425
/// Edges do not affect timestamps, so we only need to know the connectivity.
368
426
/// Indexed by operator index then output port.
369
- edges : Vec < Vec < Vec < Target > > > ,
427
+ edges : ColumnVec < ColumnVec < Vec < Target > > > ,
370
428
371
429
// TODO: All of the sizes of these allocations are static (except internal to `ChangeBatch`).
372
430
// It seems we should be able to flatten most of these so that there are a few allocations
@@ -544,10 +602,15 @@ impl<T:Timestamp> Tracker<T> {
544
602
let scope_outputs = builder. shape [ 0 ] . 0 ;
545
603
let output_changes = vec ! [ ChangeBatch :: new( ) ; scope_outputs] ;
546
604
605
+ let mut edges: ColumnVec < ColumnVec < Vec < Target > > > = Default :: default ( ) ;
606
+ for edge in builder. edges {
607
+ edges. push ( edge) ;
608
+ }
609
+
547
610
let tracker =
548
611
Tracker {
549
612
nodes : builder. nodes ,
550
- edges : builder . edges ,
613
+ edges,
551
614
per_operator,
552
615
target_changes : ChangeBatch :: new ( ) ,
553
616
source_changes : ChangeBatch :: new ( ) ,
@@ -663,10 +726,10 @@ impl<T:Timestamp> Tracker<T> {
663
726
. update_iter ( Some ( ( time, diff) ) ) ;
664
727
665
728
for ( time, diff) in changes {
666
- let nodes = & self . nodes [ location. node ] [ port_index] ;
729
+ let nodes = & self . nodes . index ( location. node ) . index ( port_index) ;
667
730
for ( output_port, summaries) in nodes. iter ( ) . enumerate ( ) {
668
731
let source = Location { node : location. node , port : Port :: Source ( output_port) } ;
669
- for summary in summaries. elements ( ) . iter ( ) {
732
+ for summary in summaries. iter ( ) {
670
733
if let Some ( new_time) = summary. results_in ( & time) {
671
734
self . worklist . push ( Reverse ( ( new_time, source, diff) ) ) ;
672
735
}
@@ -686,7 +749,7 @@ impl<T:Timestamp> Tracker<T> {
686
749
. update_iter ( Some ( ( time, diff) ) ) ;
687
750
688
751
for ( time, diff) in changes {
689
- for new_target in self . edges [ location. node ] [ port_index] . iter ( ) {
752
+ for new_target in self . edges . index ( location. node ) . index ( port_index) . iter ( ) {
690
753
self . worklist . push ( Reverse ( (
691
754
time. clone ( ) ,
692
755
Location :: from ( * new_target) ,
@@ -738,7 +801,7 @@ impl<T:Timestamp> Tracker<T> {
738
801
/// Graph locations may be missing from the output, in which case they have no
739
802
/// paths to scope outputs.
740
803
fn summarize_outputs < T : Timestamp > (
741
- nodes : & Vec < Vec < Vec < Antichain < T :: Summary > > > > ,
804
+ nodes : & ColumnVec < ColumnVec < VecAntichain < Vec < T :: Summary > > > > ,
742
805
edges : & Vec < Vec < Vec < Target > > > ,
743
806
) -> HashMap < Location , Vec < Antichain < T :: Summary > > >
744
807
{
@@ -780,7 +843,7 @@ fn summarize_outputs<T: Timestamp>(
780
843
Port :: Source ( output_port) => {
781
844
782
845
// Consider each input port of the associated operator.
783
- for ( input_port, summaries) in nodes[ location. node ] . iter ( ) . enumerate ( ) {
846
+ for ( input_port, summaries) in nodes. index ( location. node ) . iter ( ) . enumerate ( ) {
784
847
785
848
// Determine the current path summaries from the input port.
786
849
let location = Location { node : location. node , port : Port :: Target ( input_port) } ;
@@ -792,7 +855,7 @@ fn summarize_outputs<T: Timestamp>(
792
855
while antichains. len ( ) <= output { antichains. push ( Antichain :: new ( ) ) ; }
793
856
794
857
// Combine each operator-internal summary to the output with `summary`.
795
- for operator_summary in summaries[ output_port ] . elements ( ) . iter ( ) {
858
+ for operator_summary in summaries. index ( output_port ) . iter ( ) {
796
859
if let Some ( combined) = operator_summary. followed_by ( & summary) {
797
860
if antichains[ output] . insert ( combined. clone ( ) ) {
798
861
worklist. push_back ( ( location, output, combined) ) ;
0 commit comments