From 8c5bc990cc74287bf8c6c2d52bea5f643452baa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 10 Sep 2023 13:56:23 +0200 Subject: [PATCH 1/3] Store a index per dep node kind --- .../src/dep_graph/serialized.rs | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 4ba0cb31d0b..f689ed75168 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -46,6 +46,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use std::iter; use std::marker::PhantomData; // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits @@ -81,8 +82,9 @@ pub struct SerializedDepGraph { /// A flattened list of all edge targets in the graph, stored in the same /// varint encoding that we use on disk. Edge sources are implicit in edge_list_indices. edge_list_data: Vec, - /// Reciprocal map to `nodes`. - index: FxHashMap, SerializedDepNodeIndex>, + /// Stores a map from fingerprints to nodes per dep node kind. + /// This is the reciprocal of `nodes`. + index: Vec>, } impl Default for SerializedDepGraph { @@ -137,7 +139,7 @@ pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode) -> Option { - self.index.get(dep_node).cloned() + self.index.get(dep_node.kind.to_u16() as usize)?.get(&dep_node.hash).cloned() } #[inline] @@ -147,7 +149,7 @@ pub fn fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fi #[inline] pub fn node_count(&self) -> usize { - self.index.len() + self.nodes.len() } } @@ -220,7 +222,8 @@ fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph { for _index in 0..node_count { // Decode the header for this edge; the header packs together as many of the fixed-size // fields as possible to limit the number of times we update decoder state. - let node_header = SerializedNodeHeader { bytes: d.read_array(), _marker: PhantomData }; + let node_header = + SerializedNodeHeader:: { bytes: d.read_array(), _marker: PhantomData }; let _i: SerializedDepNodeIndex = nodes.push(node_header.node()); debug_assert_eq!(_i.index(), _index); @@ -251,8 +254,12 @@ fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph { // end of the array. This padding ensure it doesn't. edge_list_data.extend(&[0u8; DEP_NODE_PAD]); - let index: FxHashMap<_, _> = - nodes.iter_enumerated().map(|(idx, &dep_node)| (dep_node, idx)).collect(); + let mut index: Vec<_> = + iter::repeat(FxHashMap::default()).take(K::MAX as usize + 1).collect(); + + for (idx, node) in nodes.iter_enumerated() { + index[node.kind.to_u16() as usize].insert(node.hash, idx); + } SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data, index } } From 734e5a1fbd9a1a6bd0dd3058d0b428f277719cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 11 Sep 2023 17:09:28 +0200 Subject: [PATCH 2/3] Encode the number of dep kinds encountered in the dep graph --- .../src/dep_graph/serialized.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index f689ed75168..b3d64bb85f0 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -254,8 +254,10 @@ fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph { // end of the array. This padding ensure it doesn't. edge_list_data.extend(&[0u8; DEP_NODE_PAD]); - let mut index: Vec<_> = - iter::repeat(FxHashMap::default()).take(K::MAX as usize + 1).collect(); + // Read the number of each dep kind and use it to create an hash map with a suitable size. + let mut index: Vec<_> = (0..(K::MAX as usize + 1)) + .map(|_| FxHashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default())) + .collect(); for (idx, node) in nodes.iter_enumerated() { index[node.kind.to_u16() as usize].insert(node.hash, idx); @@ -426,6 +428,9 @@ struct EncoderState { total_node_count: usize, total_edge_count: usize, stats: Option>>, + + /// Stores the number of times we've encoded each dep kind. + kind_stats: Vec, } impl EncoderState { @@ -435,6 +440,7 @@ fn new(encoder: FileEncoder, record_stats: bool) -> Self { total_edge_count: 0, total_node_count: 0, stats: record_stats.then(FxHashMap::default), + kind_stats: iter::repeat(0).take(K::MAX as usize + 1).collect(), } } @@ -445,6 +451,7 @@ fn encode_node( ) -> DepNodeIndex { let index = DepNodeIndex::new(self.total_node_count); self.total_node_count += 1; + self.kind_stats[node.node.kind.to_u16() as usize] += 1; let edge_count = node.edges.len(); self.total_edge_count += edge_count; @@ -470,11 +477,16 @@ fn encode_node( } fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { - let Self { mut encoder, total_node_count, total_edge_count, stats: _ } = self; + let Self { mut encoder, total_node_count, total_edge_count, stats: _, kind_stats } = self; let node_count = total_node_count.try_into().unwrap(); let edge_count = total_edge_count.try_into().unwrap(); + // Encode the number of each dep kind encountered + for count in kind_stats.iter() { + count.encode(&mut encoder); + } + debug!(?node_count, ?edge_count); debug!("position: {:?}", encoder.position()); IntEncodedWithFixedSize(node_count).encode(&mut encoder); From f8ad88be81257c3be04a4ff1f18bd9277f7b04cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 12 Sep 2023 08:59:37 +0200 Subject: [PATCH 3/3] Use `UnhashMap` for the index --- compiler/rustc_query_system/src/dep_graph/serialized.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index b3d64bb85f0..213e5c8ba68 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -43,6 +43,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::Lock; +use rustc_data_structures::unhash::UnhashMap; use rustc_index::{Idx, IndexVec}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -84,7 +85,7 @@ pub struct SerializedDepGraph { edge_list_data: Vec, /// Stores a map from fingerprints to nodes per dep node kind. /// This is the reciprocal of `nodes`. - index: Vec>, + index: Vec>, } impl Default for SerializedDepGraph { @@ -256,7 +257,7 @@ fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph { // Read the number of each dep kind and use it to create an hash map with a suitable size. let mut index: Vec<_> = (0..(K::MAX as usize + 1)) - .map(|_| FxHashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default())) + .map(|_| UnhashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default())) .collect(); for (idx, node) in nodes.iter_enumerated() {