Skip to content

Commit a3417bf

Browse files
incr.comp.: Use a more efficient encoding for the on-disk dependency graph.
1 parent 0cbb8b5 commit a3417bf

File tree

3 files changed

+110
-58
lines changed

3 files changed

+110
-58
lines changed

src/librustc_incremental/persist/data.rs

+34-7
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,20 @@ use rustc::ich::Fingerprint;
1717
use rustc::middle::cstore::EncodedMetadataHash;
1818
use std::sync::Arc;
1919
use rustc_data_structures::fx::FxHashMap;
20+
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
2021

2122
/// Data for use when recompiling the **current crate**.
2223
#[derive(Debug, RustcEncodable, RustcDecodable)]
2324
pub struct SerializedDepGraph {
24-
pub edges: Vec<SerializedEdgeSet>,
25+
/// The set of all DepNodes in the graph
26+
pub nodes: IndexVec<DepNodeIndex, DepNode<DefPathHash>>,
27+
/// For each DepNode, stores the list of edges originating from that
28+
/// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
29+
/// which holds the actual DepNodeIndices of the target nodes.
30+
pub edge_list_indices: Vec<(u32, u32)>,
31+
/// A flattened list of all edge targets in the graph. Edge sources are
32+
/// implicit in edge_list_indices.
33+
pub edge_list_data: Vec<DepNodeIndex>,
2534

2635
/// These are output nodes that have no incoming edges. We track
2736
/// these separately so that when we reload all edges, we don't
@@ -50,12 +59,30 @@ pub struct SerializedDepGraph {
5059
pub hashes: Vec<SerializedHash>,
5160
}
5261

53-
/// Represents a set of "reduced" dependency edge. We group the
54-
/// outgoing edges from a single source together.
55-
#[derive(Debug, RustcEncodable, RustcDecodable)]
56-
pub struct SerializedEdgeSet {
57-
pub source: DepNode<DefPathHash>,
58-
pub targets: Vec<DepNode<DefPathHash>>
62+
/// The index of a DepNode in the SerializedDepGraph::nodes array.
63+
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug,
64+
RustcEncodable, RustcDecodable)]
65+
pub struct DepNodeIndex(pub u32);
66+
67+
impl DepNodeIndex {
68+
#[inline]
69+
pub fn new(idx: usize) -> DepNodeIndex {
70+
assert!(idx <= ::std::u32::MAX as usize);
71+
DepNodeIndex(idx as u32)
72+
}
73+
}
74+
75+
impl Idx for DepNodeIndex {
76+
#[inline]
77+
fn new(idx: usize) -> Self {
78+
assert!(idx <= ::std::u32::MAX as usize);
79+
DepNodeIndex(idx as u32)
80+
}
81+
82+
#[inline]
83+
fn index(self) -> usize {
84+
self.0 as usize
85+
}
5986
}
6087

6188
#[derive(Debug, RustcEncodable, RustcDecodable)]

src/librustc_incremental/persist/load.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc::ty::TyCtxt;
2020
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
2121
use rustc_serialize::Decodable as RustcDecodable;
2222
use rustc_serialize::opaque::Decoder;
23+
use std::default::Default;
2324
use std::path::{Path};
2425
use std::sync::Arc;
2526

@@ -161,10 +162,23 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
161162

162163
let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?;
163164

164-
let edge_map: FxHashMap<_, _> = serialized_dep_graph.edges
165-
.into_iter()
166-
.map(|s| (s.source, s.targets))
167-
.collect();
165+
let edge_map: FxHashMap<DepNode<DefPathHash>, Vec<DepNode<DefPathHash>>> = {
166+
let capacity = serialized_dep_graph.edge_list_data.len();
167+
let mut edge_map = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
168+
169+
for (node_index, source) in serialized_dep_graph.nodes.iter().enumerate() {
170+
let (start, end) = serialized_dep_graph.edge_list_indices[node_index];
171+
let targets =
172+
(&serialized_dep_graph.edge_list_data[start as usize .. end as usize])
173+
.into_iter()
174+
.map(|&node_index| serialized_dep_graph.nodes[node_index].clone())
175+
.collect();
176+
177+
edge_map.insert(source.clone(), targets);
178+
}
179+
180+
edge_map
181+
};
168182

169183
// Compute the set of nodes from the old graph where some input
170184
// has changed or been removed. These are "raw" source nodes,

src/librustc_incremental/persist/save.rs

+58-47
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111
use rustc::dep_graph::DepNode;
1212
use rustc::hir::def_id::DefId;
1313
use rustc::hir::svh::Svh;
14+
use rustc::hir::map::DefPathHash;
1415
use rustc::ich::Fingerprint;
1516
use rustc::middle::cstore::EncodedMetadataHashes;
1617
use rustc::session::Session;
1718
use rustc::ty::TyCtxt;
1819
use rustc_data_structures::fx::FxHashMap;
20+
use rustc_data_structures::graph;
21+
use rustc_data_structures::indexed_vec::IndexVec;
1922
use rustc_serialize::Encodable as RustcEncodable;
2023
use rustc_serialize::opaque::Encoder;
2124
use std::io::{self, Cursor, Write};
@@ -175,65 +178,73 @@ pub fn encode_dep_graph(tcx: TyCtxt,
175178
dep_node.map_def(|&def_id| Some(tcx.def_path_hash(def_id))).unwrap()
176179
};
177180

178-
// Create a flat list of (Input, WorkProduct) edges for
179-
// serialization.
180-
let mut edges = FxHashMap();
181-
for edge in preds.reduced_graph.all_edges() {
182-
let source = *preds.reduced_graph.node_data(edge.source());
183-
let target = *preds.reduced_graph.node_data(edge.target());
184-
match *target {
185-
DepNode::MetaData(ref def_id) => {
186-
// Metadata *targets* are always local metadata nodes. We have
187-
// already handled those in `encode_metadata_hashes`.
188-
assert!(def_id.is_local());
189-
continue;
190-
}
191-
_ => (),
192-
}
193-
debug!("serialize edge: {:?} -> {:?}", source, target);
194-
let source = to_hash_based_node(source);
195-
let target = to_hash_based_node(target);
196-
edges.entry(source).or_insert(vec![]).push(target);
197-
}
181+
// NB: We rely on this Vec being indexable by reduced_graph's NodeIndex.
182+
let nodes: IndexVec<DepNodeIndex, DepNode<DefPathHash>> = preds
183+
.reduced_graph
184+
.all_nodes()
185+
.iter()
186+
.map(|node| to_hash_based_node(node.data))
187+
.collect();
198188

199-
if tcx.sess.opts.debugging_opts.incremental_dump_hash {
200-
for (dep_node, hash) in &preds.hashes {
201-
println!("HIR hash for {:?} is {}", dep_node, hash);
189+
let mut edge_list_indices = Vec::with_capacity(nodes.len());
190+
let mut edge_list_data = Vec::with_capacity(preds.reduced_graph.len_edges());
191+
192+
for node_index in 0 .. nodes.len() {
193+
let start = edge_list_data.len() as u32;
194+
195+
for target in preds.reduced_graph.successor_nodes(graph::NodeIndex(node_index)) {
196+
edge_list_data.push(DepNodeIndex::new(target.node_id()));
202197
}
198+
199+
let end = edge_list_data.len() as u32;
200+
debug_assert_eq!(node_index, edge_list_indices.len());
201+
edge_list_indices.push((start, end));
203202
}
204203

205-
// Create the serialized dep-graph.
206-
let bootstrap_outputs = preds.bootstrap_outputs
207-
.iter()
208-
.map(|n| to_hash_based_node(n))
209-
.collect();
210-
let edges = edges.into_iter()
211-
.map(|(k, v)| SerializedEdgeSet { source: k, targets: v })
212-
.collect();
204+
// Let's make we had no overflow there.
205+
assert!(edge_list_data.len() <= ::std::u32::MAX as usize);
206+
// Check that we have a consistent number of edges.
207+
assert_eq!(edge_list_data.len(), preds.reduced_graph.len_edges());
208+
209+
let bootstrap_outputs = preds
210+
.bootstrap_outputs
211+
.iter()
212+
.map(|n| to_hash_based_node(n))
213+
.collect();
214+
215+
let hashes = preds
216+
.hashes
217+
.iter()
218+
.map(|(&dep_node, &hash)| {
219+
SerializedHash {
220+
dep_node: to_hash_based_node(dep_node),
221+
hash: hash,
222+
}
223+
})
224+
.collect();
225+
213226
let graph = SerializedDepGraph {
227+
nodes,
228+
edge_list_indices,
229+
edge_list_data,
214230
bootstrap_outputs,
215-
edges,
216-
hashes: preds.hashes
217-
.iter()
218-
.map(|(&dep_node, &hash)| {
219-
SerializedHash {
220-
dep_node: to_hash_based_node(dep_node),
221-
hash: hash,
222-
}
223-
})
224-
.collect(),
231+
hashes,
225232
};
226233

234+
// Encode the graph data.
235+
graph.encode(encoder)?;
236+
227237
if tcx.sess.opts.debugging_opts.incremental_info {
228-
println!("incremental: {} nodes in reduced dep-graph", preds.reduced_graph.len_nodes());
229-
println!("incremental: {} edges in serialized dep-graph", graph.edges.len());
238+
println!("incremental: {} nodes in reduced dep-graph", graph.nodes.len());
239+
println!("incremental: {} edges in serialized dep-graph", graph.edge_list_data.len());
230240
println!("incremental: {} hashes in serialized dep-graph", graph.hashes.len());
231241
}
232242

233-
debug!("graph = {:#?}", graph);
234-
235-
// Encode the graph data.
236-
graph.encode(encoder)?;
243+
if tcx.sess.opts.debugging_opts.incremental_dump_hash {
244+
for (dep_node, hash) in &preds.hashes {
245+
println!("ICH for {:?} is {}", dep_node, hash);
246+
}
247+
}
237248

238249
Ok(())
239250
}

0 commit comments

Comments
 (0)