1 //! The data that we will serialize and deserialize. 2 //! 3 //! The dep-graph is serialized as a sequence of NodeInfo, with the dependencies 4 //! specified inline. The total number of nodes and edges are stored as the last 5 //! 16 bytes of the file, so we can find them easily at decoding time. 6 //! 7 //! The serialisation is performed on-demand when each node is emitted. Using this 8 //! scheme, we do not need to keep the current graph in memory. 9 //! 10 //! The deserialization is performed manually, in order to convert from the stored 11 //! sequence of NodeInfos to the different arrays in SerializedDepGraph. Since the 12 //! node and edge count are stored at the end of the file, all the arrays can be 13 //! pre-allocated with the right length. 14 15 use super::query::DepGraphQuery; 16 use super::{DepKind, DepNode, DepNodeIndex}; 17 use rustc_data_structures::fingerprint::Fingerprint; 18 use rustc_data_structures::fx::FxHashMap; 19 use rustc_data_structures::profiling::SelfProfilerRef; 20 use rustc_data_structures::sync::Lock; 21 use rustc_index::{Idx, IndexVec}; 22 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; 23 use rustc_serialize::{Decodable, Decoder, Encodable}; 24 use smallvec::SmallVec; 25 26 // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits 27 // unused so that we can store multiple index types in `CompressedHybridIndex`, 28 // and use those bits to encode which index type it contains. 29 rustc_index::newtype_index! { 30 #[max = 0x7FFF_FFFF] 31 pub struct SerializedDepNodeIndex {} 32 } 33 34 /// Data for use when recompiling the **current crate**. 35 #[derive(Debug)] 36 pub struct SerializedDepGraph<K: DepKind> { 37 /// The set of all DepNodes in the graph 38 nodes: IndexVec<SerializedDepNodeIndex, DepNode<K>>, 39 /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to 40 /// the DepNode at the same index in the nodes vector. 41 fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>, 42 /// For each DepNode, stores the list of edges originating from that 43 /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data, 44 /// which holds the actual DepNodeIndices of the target nodes. 45 edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>, 46 /// A flattened list of all edge targets in the graph. Edge sources are 47 /// implicit in edge_list_indices. 48 edge_list_data: Vec<SerializedDepNodeIndex>, 49 /// Reciprocal map to `nodes`. 50 index: FxHashMap<DepNode<K>, SerializedDepNodeIndex>, 51 } 52 53 impl<K: DepKind> Default for SerializedDepGraph<K> { default() -> Self54 fn default() -> Self { 55 SerializedDepGraph { 56 nodes: Default::default(), 57 fingerprints: Default::default(), 58 edge_list_indices: Default::default(), 59 edge_list_data: Default::default(), 60 index: Default::default(), 61 } 62 } 63 } 64 65 impl<K: DepKind> SerializedDepGraph<K> { 66 #[inline] edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex]67 pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] { 68 let targets = self.edge_list_indices[source]; 69 &self.edge_list_data[targets.0 as usize..targets.1 as usize] 70 } 71 72 #[inline] index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode<K>73 pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode<K> { 74 self.nodes[dep_node_index] 75 } 76 77 #[inline] node_to_index_opt(&self, dep_node: &DepNode<K>) -> Option<SerializedDepNodeIndex>78 pub fn node_to_index_opt(&self, dep_node: &DepNode<K>) -> Option<SerializedDepNodeIndex> { 79 self.index.get(dep_node).cloned() 80 } 81 82 #[inline] fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fingerprint83 pub fn fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fingerprint { 84 self.fingerprints[dep_node_index] 85 } 86 node_count(&self) -> usize87 pub fn node_count(&self) -> usize { 88 self.index.len() 89 } 90 } 91 92 impl<'a, K: DepKind + Decodable<MemDecoder<'a>>> Decodable<MemDecoder<'a>> 93 for SerializedDepGraph<K> 94 { 95 #[instrument(level = "debug", skip(d))] decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph<K>96 fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph<K> { 97 // The last 16 bytes are the node count and edge count. 98 debug!("position: {:?}", d.position()); 99 let (node_count, edge_count) = 100 d.with_position(d.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { 101 debug!("position: {:?}", d.position()); 102 let node_count = IntEncodedWithFixedSize::decode(d).0 as usize; 103 let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize; 104 (node_count, edge_count) 105 }); 106 debug!("position: {:?}", d.position()); 107 108 debug!(?node_count, ?edge_count); 109 110 let mut nodes = IndexVec::with_capacity(node_count); 111 let mut fingerprints = IndexVec::with_capacity(node_count); 112 let mut edge_list_indices = IndexVec::with_capacity(node_count); 113 let mut edge_list_data = Vec::with_capacity(edge_count); 114 115 for _index in 0..node_count { 116 let dep_node: DepNode<K> = Decodable::decode(d); 117 let _i: SerializedDepNodeIndex = nodes.push(dep_node); 118 debug_assert_eq!(_i.index(), _index); 119 120 let fingerprint: Fingerprint = Decodable::decode(d); 121 let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint); 122 debug_assert_eq!(_i.index(), _index); 123 124 // Deserialize edges -- sequence of DepNodeIndex 125 let len = d.read_usize(); 126 let start = edge_list_data.len().try_into().unwrap(); 127 for _ in 0..len { 128 let edge = Decodable::decode(d); 129 edge_list_data.push(edge); 130 } 131 let end = edge_list_data.len().try_into().unwrap(); 132 let _i: SerializedDepNodeIndex = edge_list_indices.push((start, end)); 133 debug_assert_eq!(_i.index(), _index); 134 } 135 136 let index: FxHashMap<_, _> = 137 nodes.iter_enumerated().map(|(idx, &dep_node)| (dep_node, idx)).collect(); 138 139 SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data, index } 140 } 141 } 142 143 #[derive(Debug, Encodable, Decodable)] 144 pub struct NodeInfo<K: DepKind> { 145 node: DepNode<K>, 146 fingerprint: Fingerprint, 147 edges: SmallVec<[DepNodeIndex; 8]>, 148 } 149 150 struct Stat<K: DepKind> { 151 kind: K, 152 node_counter: u64, 153 edge_counter: u64, 154 } 155 156 struct EncoderState<K: DepKind> { 157 encoder: FileEncoder, 158 total_node_count: usize, 159 total_edge_count: usize, 160 stats: Option<FxHashMap<K, Stat<K>>>, 161 } 162 163 impl<K: DepKind> EncoderState<K> { new(encoder: FileEncoder, record_stats: bool) -> Self164 fn new(encoder: FileEncoder, record_stats: bool) -> Self { 165 Self { 166 encoder, 167 total_edge_count: 0, 168 total_node_count: 0, 169 stats: record_stats.then(FxHashMap::default), 170 } 171 } 172 encode_node( &mut self, node: &NodeInfo<K>, record_graph: &Option<Lock<DepGraphQuery<K>>>, ) -> DepNodeIndex173 fn encode_node( 174 &mut self, 175 node: &NodeInfo<K>, 176 record_graph: &Option<Lock<DepGraphQuery<K>>>, 177 ) -> DepNodeIndex { 178 let index = DepNodeIndex::new(self.total_node_count); 179 self.total_node_count += 1; 180 181 let edge_count = node.edges.len(); 182 self.total_edge_count += edge_count; 183 184 if let Some(record_graph) = &record_graph { 185 // Do not ICE when a query is called from within `with_query`. 186 if let Some(record_graph) = &mut record_graph.try_lock() { 187 record_graph.push(index, node.node, &node.edges); 188 } 189 } 190 191 if let Some(stats) = &mut self.stats { 192 let kind = node.node.kind; 193 194 let stat = stats.entry(kind).or_insert(Stat { kind, node_counter: 0, edge_counter: 0 }); 195 stat.node_counter += 1; 196 stat.edge_counter += edge_count as u64; 197 } 198 199 let encoder = &mut self.encoder; 200 node.encode(encoder); 201 index 202 } 203 finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult204 fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { 205 let Self { mut encoder, total_node_count, total_edge_count, stats: _ } = self; 206 207 let node_count = total_node_count.try_into().unwrap(); 208 let edge_count = total_edge_count.try_into().unwrap(); 209 210 debug!(?node_count, ?edge_count); 211 debug!("position: {:?}", encoder.position()); 212 IntEncodedWithFixedSize(node_count).encode(&mut encoder); 213 IntEncodedWithFixedSize(edge_count).encode(&mut encoder); 214 debug!("position: {:?}", encoder.position()); 215 // Drop the encoder so that nothing is written after the counts. 216 let result = encoder.finish(); 217 if let Ok(position) = result { 218 // FIXME(rylev): we hardcode the dep graph file name so we 219 // don't need a dependency on rustc_incremental just for that. 220 profiler.artifact_size("dep_graph", "dep-graph.bin", position as u64); 221 } 222 result 223 } 224 } 225 226 pub struct GraphEncoder<K: DepKind> { 227 status: Lock<EncoderState<K>>, 228 record_graph: Option<Lock<DepGraphQuery<K>>>, 229 } 230 231 impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> { new( encoder: FileEncoder, prev_node_count: usize, record_graph: bool, record_stats: bool, ) -> Self232 pub fn new( 233 encoder: FileEncoder, 234 prev_node_count: usize, 235 record_graph: bool, 236 record_stats: bool, 237 ) -> Self { 238 let record_graph = record_graph.then(|| Lock::new(DepGraphQuery::new(prev_node_count))); 239 let status = Lock::new(EncoderState::new(encoder, record_stats)); 240 GraphEncoder { status, record_graph } 241 } 242 with_query(&self, f: impl Fn(&DepGraphQuery<K>))243 pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery<K>)) { 244 if let Some(record_graph) = &self.record_graph { 245 f(&record_graph.lock()) 246 } 247 } 248 print_incremental_info( &self, total_read_count: u64, total_duplicate_read_count: u64, )249 pub(crate) fn print_incremental_info( 250 &self, 251 total_read_count: u64, 252 total_duplicate_read_count: u64, 253 ) { 254 let status = self.status.lock(); 255 if let Some(record_stats) = &status.stats { 256 let mut stats: Vec<_> = record_stats.values().collect(); 257 stats.sort_by_key(|s| -(s.node_counter as i64)); 258 259 const SEPARATOR: &str = "[incremental] --------------------------------\ 260 ----------------------------------------------\ 261 ------------"; 262 263 eprintln!("[incremental]"); 264 eprintln!("[incremental] DepGraph Statistics"); 265 eprintln!("{SEPARATOR}"); 266 eprintln!("[incremental]"); 267 eprintln!("[incremental] Total Node Count: {}", status.total_node_count); 268 eprintln!("[incremental] Total Edge Count: {}", status.total_edge_count); 269 270 if cfg!(debug_assertions) { 271 eprintln!("[incremental] Total Edge Reads: {total_read_count}"); 272 eprintln!("[incremental] Total Duplicate Edge Reads: {total_duplicate_read_count}"); 273 } 274 275 eprintln!("[incremental]"); 276 eprintln!( 277 "[incremental] {:<36}| {:<17}| {:<12}| {:<17}|", 278 "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count" 279 ); 280 eprintln!("{SEPARATOR}"); 281 282 for stat in stats { 283 let node_kind_ratio = 284 (100.0 * (stat.node_counter as f64)) / (status.total_node_count as f64); 285 let node_kind_avg_edges = (stat.edge_counter as f64) / (stat.node_counter as f64); 286 287 eprintln!( 288 "[incremental] {:<36}|{:>16.1}% |{:>12} |{:>17.1} |", 289 format!("{:?}", stat.kind), 290 node_kind_ratio, 291 stat.node_counter, 292 node_kind_avg_edges, 293 ); 294 } 295 296 eprintln!("{SEPARATOR}"); 297 eprintln!("[incremental]"); 298 } 299 } 300 send( &self, profiler: &SelfProfilerRef, node: DepNode<K>, fingerprint: Fingerprint, edges: SmallVec<[DepNodeIndex; 8]>, ) -> DepNodeIndex301 pub(crate) fn send( 302 &self, 303 profiler: &SelfProfilerRef, 304 node: DepNode<K>, 305 fingerprint: Fingerprint, 306 edges: SmallVec<[DepNodeIndex; 8]>, 307 ) -> DepNodeIndex { 308 let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph"); 309 let node = NodeInfo { node, fingerprint, edges }; 310 self.status.lock().encode_node(&node, &self.record_graph) 311 } 312 finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult313 pub fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { 314 let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph"); 315 self.status.into_inner().finish(profiler) 316 } 317 } 318