@@ -41,14 +41,17 @@ use crate::dep_graph::EdgesVec;
4141use rustc_data_structures:: fingerprint:: Fingerprint ;
4242use rustc_data_structures:: fingerprint:: PackedFingerprint ;
4343use rustc_data_structures:: fx:: FxHashMap ;
44+ use rustc_data_structures:: outline;
4445use rustc_data_structures:: profiling:: SelfProfilerRef ;
4546use rustc_data_structures:: sync:: Lock ;
4647use rustc_data_structures:: unhash:: UnhashMap ;
4748use rustc_index:: { Idx , IndexVec } ;
4849use rustc_serialize:: opaque:: { FileEncodeResult , FileEncoder , IntEncodedWithFixedSize , MemDecoder } ;
4950use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
50- use std :: iter ;
51+ use rustc_session :: Session ;
5152use std:: marker:: PhantomData ;
53+ use std:: sync:: { Arc , OnceLock } ;
54+ use std:: { iter, thread} ;
5255
5356// The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
5457// unused so that we can store multiple index types in `CompressedHybridIndex`,
@@ -69,23 +72,33 @@ const DEP_NODE_PAD: usize = DEP_NODE_SIZE - 1;
6972const DEP_NODE_WIDTH_BITS : usize = DEP_NODE_SIZE / 2 ;
7073
7174/// Data for use when recompiling the **current crate**.
72- #[ derive( Debug ) ]
7375pub struct SerializedDepGraph {
7476 /// The set of all DepNodes in the graph
7577 nodes : IndexVec < SerializedDepNodeIndex , DepNode > ,
78+
7679 /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
7780 /// the DepNode at the same index in the nodes vector.
7881 fingerprints : IndexVec < SerializedDepNodeIndex , Fingerprint > ,
82+
7983 /// For each DepNode, stores the list of edges originating from that
8084 /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
8185 /// which holds the actual DepNodeIndices of the target nodes.
8286 edge_list_indices : IndexVec < SerializedDepNodeIndex , EdgeHeader > ,
87+
8388 /// A flattened list of all edge targets in the graph, stored in the same
8489 /// varint encoding that we use on disk. Edge sources are implicit in edge_list_indices.
8590 edge_list_data : Vec < u8 > ,
91+
8692 /// 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 ,
89102}
90103
91104impl Default for SerializedDepGraph {
@@ -96,6 +109,8 @@ impl Default for SerializedDepGraph {
96109 edge_list_indices : Default :: default ( ) ,
97110 edge_list_data : Default :: default ( ) ,
98111 index : Default :: default ( ) ,
112+ index_sizes : Default :: default ( ) ,
113+ prof : SelfProfilerRef :: new ( None , None ) ,
99114 }
100115 }
101116}
@@ -138,9 +153,35 @@ impl SerializedDepGraph {
138153 self . nodes [ dep_node_index]
139154 }
140155
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+
141175 #[ inline]
142176 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 ( )
144185 }
145186
146187 #[ inline]
@@ -152,6 +193,31 @@ impl SerializedDepGraph {
152193 pub fn node_count ( & self ) -> usize {
153194 self . nodes . len ( )
154195 }
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+ }
155221}
156222
157223/// A packed representation of an edge's start index and byte width.
@@ -185,8 +251,8 @@ fn mask(bits: usize) -> usize {
185251}
186252
187253impl 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 > {
190256 // The last 16 bytes are the node count and edge count.
191257 debug ! ( "position: {:?}" , d. position( ) ) ;
192258 let ( node_count, edge_count) =
@@ -253,16 +319,21 @@ impl SerializedDepGraph {
253319 // end of the array. This padding ensure it doesn't.
254320 edge_list_data. extend ( & [ 0u8 ; DEP_NODE_PAD ] ) ;
255321
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
266337 }
267338}
268339
0 commit comments