@@ -16,11 +16,13 @@ use super::query::DepGraphQuery;
16
16
use super :: { DepKind , DepNode , DepNodeIndex } ;
17
17
use rustc_data_structures:: fingerprint:: Fingerprint ;
18
18
use rustc_data_structures:: fx:: FxHashMap ;
19
+ use rustc_data_structures:: memmap:: Mmap ;
20
+ use rustc_data_structures:: owning_ref:: OwningRef ;
19
21
use rustc_data_structures:: profiling:: SelfProfilerRef ;
20
22
use rustc_data_structures:: sync:: Lock ;
21
- use rustc_index:: vec:: { Idx , IndexVec } ;
23
+ use rustc_index:: vec:: IndexVec ;
22
24
use rustc_serialize:: opaque:: { FileEncodeResult , FileEncoder , IntEncodedWithFixedSize , MemDecoder } ;
23
- use rustc_serialize:: { Decodable , Decoder , Encodable } ;
25
+ use rustc_serialize:: { Decodable , Encodable } ;
24
26
use smallvec:: SmallVec ;
25
27
use std:: convert:: TryInto ;
26
28
@@ -34,138 +36,136 @@ rustc_index::newtype_index! {
34
36
}
35
37
36
38
/// Data for use when recompiling the **current crate**.
37
- #[ derive( Debug ) ]
39
+ ///
40
+ /// The DepGraph is backed on-disk and read on-demand through a Mmap.
41
+ /// The file layout is as follows.
42
+ ///
43
+ /// The DepGraph starts with the version header, handled by rustc_incremental.
44
+ /// It is followed by the concatenation of all node dependency information as:
45
+ /// - the query result fingerprint (size_of<Fingerprint> bytes)
46
+ /// - the number of dependency edges (4 bytes)
47
+ /// - the dependencies indices (array of 4-byte integers)
48
+ ///
49
+ /// Finding this information inside the file is handled by a "glossary" written at the end.
50
+ /// This glossary is an array of `(DepNode, u32)` pairs. This array is used to make the
51
+ /// correspondence between the `SerializedDepNodeIndex` (ie. the index into this array),
52
+ /// and the `DepNode`. The `u32` is the position of the dependency information (Fingerprint +
53
+ /// array of dependencies) inside the file. The glossary array is directly mmapped into `nodes`.
54
+ ///
55
+ /// The file finished with two `u64`, which are the number of entries in the glossary
56
+ /// and its position in the file.
57
+ ///
58
+ /// Graphically, we have:
59
+ /// beginning of nodes beginning of glossary ---------------+
60
+ /// v v |
61
+ /// --------------------------------------------------------------------------------------------
62
+ /// | HEADER | ... | Fingerprint | Length | Deps | ... | ... | DepNode | u32 | ... | u64 | u64 |
63
+ /// --------------------------------------------------------------------------------------------
64
+ /// ^ | node
65
+ /// start for node i --------------------------------------+ count
66
+ ///
67
+ /// In order to recover an index from a DepNode, we populate a hash-map in `index`.
38
68
pub struct SerializedDepGraph < K : DepKind > {
39
- /// The set of all DepNodes in the graph
40
- nodes : IndexVec < SerializedDepNodeIndex , DepNode < K > > ,
41
- /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
42
- /// the DepNode at the same index in the nodes vector.
43
- fingerprints : IndexVec < SerializedDepNodeIndex , Fingerprint > ,
44
- /// For each DepNode, stores the list of edges originating from that
45
- /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
46
- /// which holds the actual DepNodeIndices of the target nodes.
47
- edge_list_indices : IndexVec < SerializedDepNodeIndex , ( u32 , u32 ) > ,
48
- /// A flattened list of all edge targets in the graph. Edge sources are
49
- /// implicit in edge_list_indices.
50
- edge_list_data : Vec < SerializedDepNodeIndex > ,
69
+ /// The set of all DepNodes in the graph and their position in the mmap.
70
+ nodes : Option < OwningRef < Mmap , [ ( DepNode < K > , u32 ) ] > > ,
51
71
/// Reciprocal map to `nodes`.
52
72
index : FxHashMap < DepNode < K > , SerializedDepNodeIndex > ,
53
73
}
54
74
55
75
impl < K : DepKind > Default for SerializedDepGraph < K > {
56
76
fn default ( ) -> Self {
57
- SerializedDepGraph {
58
- nodes : Default :: default ( ) ,
59
- fingerprints : Default :: default ( ) ,
60
- edge_list_indices : Default :: default ( ) ,
61
- edge_list_data : Default :: default ( ) ,
62
- index : Default :: default ( ) ,
63
- }
77
+ SerializedDepGraph { nodes : None , index : Default :: default ( ) }
64
78
}
65
79
}
66
80
67
81
impl < K : DepKind > SerializedDepGraph < K > {
68
82
#[ inline]
69
- pub fn edge_targets_from ( & self , source : SerializedDepNodeIndex ) -> & [ SerializedDepNodeIndex ] {
70
- let targets = self . edge_list_indices [ source] ;
71
- & self . edge_list_data [ targets. 0 as usize ..targets. 1 as usize ]
83
+ fn decoder_at ( & self , dep_node_index : SerializedDepNodeIndex ) -> Option < MemDecoder < ' _ > > {
84
+ let nodes = self . nodes . as_ref ( ) ?;
85
+ let dep_node_index = dep_node_index. as_usize ( ) ;
86
+ let position = nodes[ dep_node_index] . 1 as usize ;
87
+ let data = & nodes. owner ( ) [ position..] ;
88
+ let decoder = MemDecoder :: new ( data, 0 ) ;
89
+ Some ( decoder)
90
+ }
91
+
92
+ #[ inline]
93
+ pub fn node_to_index_opt ( & self , dep_node : & DepNode < K > ) -> Option < SerializedDepNodeIndex > {
94
+ self . index . get ( dep_node) . cloned ( )
72
95
}
73
96
74
97
#[ inline]
75
98
pub fn index_to_node ( & self , dep_node_index : SerializedDepNodeIndex ) -> DepNode < K > {
76
- self . nodes [ dep_node_index]
99
+ let dep_node_index = dep_node_index. as_usize ( ) ;
100
+ self . nodes . as_ref ( ) . unwrap ( ) [ dep_node_index] . 0
77
101
}
78
102
79
103
#[ inline]
80
- pub fn node_to_index_opt ( & self , dep_node : & DepNode < K > ) -> Option < SerializedDepNodeIndex > {
81
- self . index . get ( dep_node) . cloned ( )
104
+ pub fn fingerprint_by_index ( & self , dep_node_index : SerializedDepNodeIndex ) -> Fingerprint {
105
+ if let Some ( decoder) = self . decoder_at ( dep_node_index) {
106
+ let & fingerprint = unsafe { decoder. mmap_at :: < Fingerprint > ( 0 ) } ;
107
+ fingerprint
108
+ } else {
109
+ Fingerprint :: ZERO
110
+ }
82
111
}
83
112
84
113
#[ inline]
85
114
pub fn fingerprint_of ( & self , dep_node : & DepNode < K > ) -> Option < Fingerprint > {
86
- self . index . get ( dep_node) . map ( |& node_index| self . fingerprints [ node_index] )
115
+ let index = self . index . get ( dep_node) . cloned ( ) ?;
116
+ Some ( self . fingerprint_by_index ( index) )
87
117
}
88
118
89
119
#[ inline]
90
- pub fn fingerprint_by_index ( & self , dep_node_index : SerializedDepNodeIndex ) -> Fingerprint {
91
- self . fingerprints [ dep_node_index]
120
+ pub fn edge_targets_from ( & self , source : SerializedDepNodeIndex ) -> & [ SerializedDepNodeIndex ] {
121
+ // The encoder has checked that there is no padding there.
122
+ if let Some ( decoder) = self . decoder_at ( source) {
123
+ let position = std:: mem:: size_of :: < Fingerprint > ( ) ;
124
+ let & length = unsafe { decoder. mmap_at :: < u32 > ( position) } ;
125
+ unsafe {
126
+ decoder. mmap_slice_at :: < SerializedDepNodeIndex > ( position + 4 , length as usize )
127
+ }
128
+ } else {
129
+ & [ ]
130
+ }
92
131
}
93
132
94
133
pub fn node_count ( & self ) -> usize {
95
134
self . index . len ( )
96
135
}
97
- }
98
136
99
- impl < ' a , K : DepKind + Decodable < MemDecoder < ' a > > > Decodable < MemDecoder < ' a > >
100
- for SerializedDepGraph < K >
101
- {
102
- #[ instrument( level = "debug" , skip( d) ) ]
103
- fn decode ( d : & mut MemDecoder < ' a > ) -> SerializedDepGraph < K > {
104
- let start_position = d. position ( ) ;
137
+ #[ instrument( level = "debug" , skip( mmap) ) ]
138
+ pub fn decode ( mmap : Mmap ) -> SerializedDepGraph < K > {
139
+ let data = mmap. as_ref ( ) ;
105
140
106
- // The last 16 bytes are the node count and edge count.
107
- debug ! ( "position: {:?}" , d . position ( ) ) ;
108
- d . set_position ( d . data . len ( ) - 2 * IntEncodedWithFixedSize :: ENCODED_SIZE ) ;
141
+ // The last 16 bytes are the node count, edge count and nodes position .
142
+ let start_position = data . len ( ) - 2 * IntEncodedWithFixedSize :: ENCODED_SIZE ;
143
+ let mut d = MemDecoder :: new ( data , start_position ) ;
109
144
debug ! ( "position: {:?}" , d. position( ) ) ;
110
145
111
- let node_count = IntEncodedWithFixedSize :: decode ( d) . 0 as usize ;
112
- let edge_count = IntEncodedWithFixedSize :: decode ( d) . 0 as usize ;
113
- debug ! ( ?node_count, ?edge_count ) ;
146
+ let node_count = IntEncodedWithFixedSize :: decode ( & mut d) . 0 as usize ;
147
+ let nodes_position = IntEncodedWithFixedSize :: decode ( & mut d) . 0 as usize ;
148
+ debug ! ( ?node_count, ?nodes_position ) ;
114
149
115
- debug ! ( "position: {:?}" , d. position( ) ) ;
116
- d. set_position ( start_position) ;
117
- debug ! ( "position: {:?}" , d. position( ) ) ;
118
-
119
- let mut nodes = IndexVec :: with_capacity ( node_count) ;
120
- let mut fingerprints = IndexVec :: with_capacity ( node_count) ;
121
- let mut edge_list_indices = IndexVec :: with_capacity ( node_count) ;
122
- let mut edge_list_data = Vec :: with_capacity ( edge_count) ;
123
-
124
- for _index in 0 ..node_count {
125
- let dep_node: DepNode < K > = Decodable :: decode ( d) ;
126
- let _i: SerializedDepNodeIndex = nodes. push ( dep_node) ;
127
- debug_assert_eq ! ( _i. index( ) , _index) ;
128
-
129
- let fingerprint: Fingerprint = Decodable :: decode ( d) ;
130
- let _i: SerializedDepNodeIndex = fingerprints. push ( fingerprint) ;
131
- debug_assert_eq ! ( _i. index( ) , _index) ;
132
-
133
- // Deserialize edges -- sequence of DepNodeIndex
134
- let len = d. read_usize ( ) ;
135
- let start = edge_list_data. len ( ) . try_into ( ) . unwrap ( ) ;
136
- for _ in 0 ..len {
137
- let edge = Decodable :: decode ( d) ;
138
- edge_list_data. push ( edge) ;
139
- }
140
- let end = edge_list_data. len ( ) . try_into ( ) . unwrap ( ) ;
141
- let _i: SerializedDepNodeIndex = edge_list_indices. push ( ( start, end) ) ;
142
- debug_assert_eq ! ( _i. index( ) , _index) ;
143
- }
150
+ let nodes = OwningRef :: new ( mmap) . map ( |mmap| {
151
+ let d = MemDecoder :: new ( mmap, nodes_position) ;
152
+ unsafe { d. mmap_slice_at :: < ( DepNode < K > , u32 ) > ( nodes_position, node_count) }
153
+ } ) ;
144
154
145
- let index: FxHashMap < _ , _ > =
146
- nodes. iter_enumerated ( ) . map ( |( idx, & dep_node) | ( dep_node, idx) ) . collect ( ) ;
155
+ let index: FxHashMap < _ , _ > = nodes
156
+ . iter ( )
157
+ . enumerate ( )
158
+ . map ( |( idx, & ( dep_node, _) ) | ( dep_node, SerializedDepNodeIndex :: from_usize ( idx) ) )
159
+ . collect ( ) ;
147
160
148
- SerializedDepGraph { nodes, fingerprints , edge_list_indices , edge_list_data , index }
161
+ SerializedDepGraph { nodes : Some ( nodes ) , index }
149
162
}
150
163
}
151
164
152
- #[ derive( Debug , Encodable , Decodable ) ]
153
- pub struct NodeInfo < K : DepKind > {
154
- node : DepNode < K > ,
155
- fingerprint : Fingerprint ,
156
- edges : SmallVec < [ DepNodeIndex ; 8 ] > ,
157
- }
158
-
159
- struct Stat < K : DepKind > {
160
- kind : K ,
161
- node_counter : u64 ,
162
- edge_counter : u64 ,
163
- }
164
-
165
165
struct EncoderState < K : DepKind > {
166
166
encoder : FileEncoder ,
167
- total_node_count : usize ,
168
167
total_edge_count : usize ,
168
+ nodes : IndexVec < DepNodeIndex , ( DepNode < K > , u32 ) > ,
169
169
stats : Option < FxHashMap < K , Stat < K > > > ,
170
170
}
171
171
@@ -174,22 +174,35 @@ impl<K: DepKind> EncoderState<K> {
174
174
Self {
175
175
encoder,
176
176
total_edge_count : 0 ,
177
- total_node_count : 0 ,
177
+ nodes : IndexVec :: default ( ) ,
178
178
stats : record_stats. then ( FxHashMap :: default) ,
179
179
}
180
180
}
181
181
182
+ fn try_encode_node ( & mut self , node : & NodeInfo < K > ) -> usize {
183
+ let encoder = & mut self . encoder ;
184
+ let start_pos = encoder. write_mmap ( & node. fingerprint ) ;
185
+ let _pos = encoder. write_mmap :: < u32 > ( & node. edges . len ( ) . try_into ( ) . unwrap ( ) ) ;
186
+ debug_assert_eq ! ( _pos, start_pos + std:: mem:: size_of:: <Fingerprint >( ) ) ;
187
+ let _pos = encoder. write_mmap_slice :: < DepNodeIndex > ( & node. edges [ ..] ) ;
188
+ debug_assert_eq ! ( _pos, start_pos + std:: mem:: size_of:: <Fingerprint >( ) + 4 ) ;
189
+ start_pos
190
+ }
191
+
182
192
fn encode_node (
183
193
& mut self ,
184
194
node : & NodeInfo < K > ,
185
195
record_graph : & Option < Lock < DepGraphQuery < K > > > ,
186
196
) -> DepNodeIndex {
187
- let index = DepNodeIndex :: new ( self . total_node_count ) ;
188
- self . total_node_count += 1 ;
189
-
190
197
let edge_count = node. edges . len ( ) ;
191
198
self . total_edge_count += edge_count;
192
199
200
+ let position = self . try_encode_node ( node) ;
201
+ debug_assert ! ( position & ( std:: mem:: align_of:: <Fingerprint >( ) - 1 ) == 0 ) ;
202
+ debug ! ( ?position) ;
203
+
204
+ let index = self . nodes . push ( ( node. node , position. try_into ( ) . unwrap ( ) ) ) ;
205
+
193
206
if let Some ( record_graph) = & record_graph {
194
207
// Do not ICE when a query is called from within `with_query`.
195
208
if let Some ( record_graph) = & mut record_graph. try_lock ( ) {
@@ -205,21 +218,20 @@ impl<K: DepKind> EncoderState<K> {
205
218
stat. edge_counter += edge_count as u64 ;
206
219
}
207
220
208
- let encoder = & mut self . encoder ;
209
- node. encode ( encoder) ;
210
221
index
211
222
}
212
223
213
224
fn finish ( self , profiler : & SelfProfilerRef ) -> FileEncodeResult {
214
- let Self { mut encoder, total_node_count , total_edge_count, stats : _ } = self ;
225
+ let Self { mut encoder, nodes , total_edge_count : _ , stats : _ } = self ;
215
226
216
- let node_count = total_node_count. try_into ( ) . unwrap ( ) ;
217
- let edge_count = total_edge_count. try_into ( ) . unwrap ( ) ;
227
+ let node_count = nodes. len ( ) . try_into ( ) . unwrap ( ) ;
228
+ let nodes_position = encoder. write_mmap_slice ( & nodes. raw [ ..] ) ;
229
+ let nodes_position = nodes_position. try_into ( ) . unwrap ( ) ;
218
230
219
- debug ! ( ?node_count, ?edge_count ) ;
231
+ debug ! ( ?node_count, ?nodes_position ) ;
220
232
debug ! ( "position: {:?}" , encoder. position( ) ) ;
221
233
IntEncodedWithFixedSize ( node_count) . encode ( & mut encoder) ;
222
- IntEncodedWithFixedSize ( edge_count ) . encode ( & mut encoder) ;
234
+ IntEncodedWithFixedSize ( nodes_position ) . encode ( & mut encoder) ;
223
235
debug ! ( "position: {:?}" , encoder. position( ) ) ;
224
236
// Drop the encoder so that nothing is written after the counts.
225
237
let result = encoder. finish ( ) ;
@@ -232,12 +244,25 @@ impl<K: DepKind> EncoderState<K> {
232
244
}
233
245
}
234
246
247
+ #[ derive( Debug , Encodable , Decodable ) ]
248
+ pub struct NodeInfo < K : DepKind > {
249
+ node : DepNode < K > ,
250
+ fingerprint : Fingerprint ,
251
+ edges : SmallVec < [ DepNodeIndex ; 8 ] > ,
252
+ }
253
+
254
+ struct Stat < K : DepKind > {
255
+ kind : K ,
256
+ node_counter : u64 ,
257
+ edge_counter : u64 ,
258
+ }
259
+
235
260
pub struct GraphEncoder < K : DepKind > {
236
261
status : Lock < EncoderState < K > > ,
237
262
record_graph : Option < Lock < DepGraphQuery < K > > > ,
238
263
}
239
264
240
- impl < K : DepKind + Encodable < FileEncoder > > GraphEncoder < K > {
265
+ impl < K : DepKind > GraphEncoder < K > {
241
266
pub fn new (
242
267
encoder : FileEncoder ,
243
268
prev_node_count : usize ,
@@ -270,11 +295,13 @@ impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
270
295
----------------------------------------------\
271
296
------------";
272
297
298
+ let total_node_count = status. nodes . len ( ) ;
299
+
273
300
eprintln ! ( "[incremental]" ) ;
274
301
eprintln ! ( "[incremental] DepGraph Statistics" ) ;
275
302
eprintln ! ( "{}" , SEPARATOR ) ;
276
303
eprintln ! ( "[incremental]" ) ;
277
- eprintln ! ( "[incremental] Total Node Count: {}" , status . total_node_count) ;
304
+ eprintln ! ( "[incremental] Total Node Count: {}" , total_node_count) ;
278
305
eprintln ! ( "[incremental] Total Edge Count: {}" , status. total_edge_count) ;
279
306
280
307
if cfg ! ( debug_assertions) {
@@ -294,7 +321,7 @@ impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
294
321
295
322
for stat in stats {
296
323
let node_kind_ratio =
297
- ( 100.0 * ( stat. node_counter as f64 ) ) / ( status . total_node_count as f64 ) ;
324
+ ( 100.0 * ( stat. node_counter as f64 ) ) / ( total_node_count as f64 ) ;
298
325
let node_kind_avg_edges = ( stat. edge_counter as f64 ) / ( stat. node_counter as f64 ) ;
299
326
300
327
eprintln ! (
0 commit comments