@@ -41,14 +41,17 @@ use crate::dep_graph::EdgesVec;
41
41
use rustc_data_structures:: fingerprint:: Fingerprint ;
42
42
use rustc_data_structures:: fingerprint:: PackedFingerprint ;
43
43
use rustc_data_structures:: fx:: FxHashMap ;
44
+ use rustc_data_structures:: outline;
44
45
use rustc_data_structures:: profiling:: SelfProfilerRef ;
45
46
use rustc_data_structures:: sync:: Lock ;
46
47
use rustc_data_structures:: unhash:: UnhashMap ;
47
48
use rustc_index:: { Idx , IndexVec } ;
48
49
use rustc_serialize:: opaque:: { FileEncodeResult , FileEncoder , IntEncodedWithFixedSize , MemDecoder } ;
49
50
use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
50
- use std :: iter ;
51
+ use rustc_session :: Session ;
51
52
use std:: marker:: PhantomData ;
53
+ use std:: sync:: { Arc , OnceLock } ;
54
+ use std:: { iter, thread} ;
52
55
53
56
// The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
54
57
// unused so that we can store multiple index types in `CompressedHybridIndex`,
@@ -69,23 +72,33 @@ const DEP_NODE_PAD: usize = DEP_NODE_SIZE - 1;
69
72
const DEP_NODE_WIDTH_BITS : usize = DEP_NODE_SIZE / 2 ;
70
73
71
74
/// Data for use when recompiling the **current crate**.
72
- #[ derive( Debug ) ]
73
75
pub struct SerializedDepGraph {
74
76
/// The set of all DepNodes in the graph
75
77
nodes : IndexVec < SerializedDepNodeIndex , DepNode > ,
78
+
76
79
/// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
77
80
/// the DepNode at the same index in the nodes vector.
78
81
fingerprints : IndexVec < SerializedDepNodeIndex , Fingerprint > ,
82
+
79
83
/// For each DepNode, stores the list of edges originating from that
80
84
/// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
81
85
/// which holds the actual DepNodeIndices of the target nodes.
82
86
edge_list_indices : IndexVec < SerializedDepNodeIndex , EdgeHeader > ,
87
+
83
88
/// A flattened list of all edge targets in the graph, stored in the same
84
89
/// varint encoding that we use on disk. Edge sources are implicit in edge_list_indices.
85
90
edge_list_data : Vec < u8 > ,
91
+
86
92
/// Stores a map from fingerprints to nodes per dep node kind.
87
- /// This is the reciprocal of `nodes`.
88
- index : Vec < UnhashMap < PackedFingerprint , SerializedDepNodeIndex > > ,
93
+ /// This is the reciprocal of `nodes`. This is computed on demand for each dep kind.
94
+ /// The entire index is also computed in a background thread.
95
+ index : Vec < OnceLock < UnhashMap < PackedFingerprint , SerializedDepNodeIndex > > > ,
96
+
97
+ /// Stores the number of node for each dep node kind.
98
+ index_sizes : Vec < usize > ,
99
+
100
+ /// A profiler reference for used in the index prefetching thread.
101
+ prof : SelfProfilerRef ,
89
102
}
90
103
91
104
impl Default for SerializedDepGraph {
@@ -96,6 +109,8 @@ impl Default for SerializedDepGraph {
96
109
edge_list_indices : Default :: default ( ) ,
97
110
edge_list_data : Default :: default ( ) ,
98
111
index : Default :: default ( ) ,
112
+ index_sizes : Default :: default ( ) ,
113
+ prof : SelfProfilerRef :: new ( None , None ) ,
99
114
}
100
115
}
101
116
}
@@ -138,9 +153,35 @@ impl SerializedDepGraph {
138
153
self . nodes [ dep_node_index]
139
154
}
140
155
156
+ /// This computes and sets up the index for just the specified `DepKind`.
157
+ fn setup_index ( & self , dep_kind : DepKind ) {
158
+ let _timer = self . prof . generic_activity ( "incr_comp_dep_graph_setup_index" ) ;
159
+
160
+ let mut index = UnhashMap :: with_capacity_and_hasher (
161
+ self . index_sizes [ dep_kind. as_usize ( ) ] ,
162
+ Default :: default ( ) ,
163
+ ) ;
164
+
165
+ for ( idx, node) in self . nodes . iter_enumerated ( ) {
166
+ if node. kind == dep_kind {
167
+ index. insert ( node. hash , idx) ;
168
+ }
169
+ }
170
+
171
+ // This may race with the prefetching thread, but that will set the same value.
172
+ self . index [ dep_kind. as_usize ( ) ] . set ( index) . ok ( ) ;
173
+ }
174
+
141
175
#[ inline]
142
176
pub fn node_to_index_opt ( & self , dep_node : & DepNode ) -> Option < SerializedDepNodeIndex > {
143
- self . index . get ( dep_node. kind . as_usize ( ) ) ?. get ( & dep_node. hash ) . cloned ( )
177
+ let index = self . index . get ( dep_node. kind . as_usize ( ) ) ?;
178
+ let index = index. get ( ) . unwrap_or_else ( || {
179
+ outline ( || {
180
+ self . setup_index ( dep_node. kind ) ;
181
+ self . index [ dep_node. kind . as_usize ( ) ] . get ( ) . unwrap ( )
182
+ } )
183
+ } ) ;
184
+ index. get ( & dep_node. hash ) . cloned ( )
144
185
}
145
186
146
187
#[ inline]
@@ -152,6 +193,31 @@ impl SerializedDepGraph {
152
193
pub fn node_count ( & self ) -> usize {
153
194
self . nodes . len ( )
154
195
}
196
+
197
+ /// This spawns a thread that prefetches the index.
198
+ fn prefetch ( self : & Arc < Self > ) {
199
+ if !self . index . is_empty ( ) {
200
+ let this = self . clone ( ) ;
201
+ thread:: spawn ( move || {
202
+ let _timer = this. prof . generic_activity ( "incr_comp_prefetch_dep_graph_index" ) ;
203
+
204
+ let mut index: Vec < _ > = this
205
+ . index_sizes
206
+ . iter ( )
207
+ . map ( |& n| UnhashMap :: with_capacity_and_hasher ( n, Default :: default ( ) ) )
208
+ . collect ( ) ;
209
+
210
+ for ( idx, node) in this. nodes . iter_enumerated ( ) {
211
+ index[ node. kind . as_usize ( ) ] . insert ( node. hash , idx) ;
212
+ }
213
+
214
+ for ( i, index) in index. into_iter ( ) . enumerate ( ) {
215
+ // This may race with `setup_index`, but that will set the same value.
216
+ this. index [ i] . set ( index) . ok ( ) ;
217
+ }
218
+ } ) ;
219
+ }
220
+ }
155
221
}
156
222
157
223
/// A packed representation of an edge's start index and byte width.
@@ -185,8 +251,8 @@ fn mask(bits: usize) -> usize {
185
251
}
186
252
187
253
impl SerializedDepGraph {
188
- #[ instrument( level = "debug" , skip( d) ) ]
189
- pub fn decode < D : Deps > ( d : & mut MemDecoder < ' _ > ) -> SerializedDepGraph {
254
+ #[ instrument( level = "debug" , skip( d, sess ) ) ]
255
+ pub fn decode < D : Deps > ( d : & mut MemDecoder < ' _ > , sess : & Session ) -> Arc < SerializedDepGraph > {
190
256
// The last 16 bytes are the node count and edge count.
191
257
debug ! ( "position: {:?}" , d. position( ) ) ;
192
258
let ( node_count, edge_count) =
@@ -253,16 +319,21 @@ impl SerializedDepGraph {
253
319
// end of the array. This padding ensure it doesn't.
254
320
edge_list_data. extend ( & [ 0u8 ; DEP_NODE_PAD ] ) ;
255
321
256
- // Read the number of each dep kind and use it to create an hash map with a suitable size.
257
- let mut index: Vec < _ > = ( 0 ..( D :: DEP_KIND_MAX + 1 ) )
258
- . map ( |_| UnhashMap :: with_capacity_and_hasher ( d. read_u32 ( ) as usize , Default :: default ( ) ) )
259
- . collect ( ) ;
260
-
261
- for ( idx, node) in nodes. iter_enumerated ( ) {
262
- index[ node. kind . as_usize ( ) ] . insert ( node. hash , idx) ;
263
- }
264
-
265
- SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data, index }
322
+ // Read the number of nodes for each dep kind.
323
+ let index_sizes: Vec < _ > =
324
+ ( 0 ..( D :: DEP_KIND_MAX + 1 ) ) . map ( |_| d. read_u32 ( ) as usize ) . collect ( ) ;
325
+
326
+ let result = Arc :: new ( SerializedDepGraph {
327
+ nodes,
328
+ fingerprints,
329
+ edge_list_indices,
330
+ edge_list_data,
331
+ index : ( 0 ..index_sizes. len ( ) ) . map ( |_| OnceLock :: new ( ) ) . collect ( ) ,
332
+ index_sizes,
333
+ prof : sess. prof . clone ( ) ,
334
+ } ) ;
335
+ result. prefetch ( ) ;
336
+ result
266
337
}
267
338
}
268
339
0 commit comments