Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d99efc8

Browse files
committed
Create the previous dep graph index on a background thread
1 parent d3c9082 commit d99efc8

File tree

4 files changed

+121
-22
lines changed

4 files changed

+121
-22
lines changed

‎compiler/rustc_incremental/src/persist/load.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_session::config::IncrementalStateAssertion;
1111
use rustc_session::{Session, StableCrateId};
1212
use rustc_span::{ErrorGuaranteed, Symbol};
1313
use std::path::{Path, PathBuf};
14+
use std::sync::Arc;
1415

1516
use super::data::*;
1617
use super::file_format;
@@ -88,7 +89,7 @@ fn delete_dirty_work_product(sess: &Session, swp: SerializedWorkProduct) {
8889
work_product::delete_workproduct_files(sess, &swp.work_product);
8990
}
9091

91-
fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProductMap)> {
92+
fn load_dep_graph(sess: &Session) -> LoadResult<(Arc<SerializedDepGraph>, WorkProductMap)> {
9293
let prof = sess.prof.clone();
9394

9495
if sess.opts.incremental.is_none() {
@@ -161,7 +162,7 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProduct
161162
return LoadResult::DataOutOfDate;
162163
}
163164

164-
let dep_graph = SerializedDepGraph::decode::<DepsType>(&mut decoder);
165+
let dep_graph = SerializedDepGraph::decode::<DepsType>(&mut decoder, sess);
165166

166167
LoadResult::Ok { data: (dep_graph, prev_work_products) }
167168
}

‎compiler/rustc_incremental/src/persist/save.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
1010
use rustc_serialize::Encodable as RustcEncodable;
1111
use rustc_session::Session;
1212
use std::fs;
13+
use std::sync::Arc;
1314

1415
use super::data::*;
1516
use super::dirty_clean;
@@ -147,7 +148,7 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult
147148
/// and moves it to the permanent dep-graph path
148149
pub(crate) fn build_dep_graph(
149150
sess: &Session,
150-
prev_graph: SerializedDepGraph,
151+
prev_graph: Arc<SerializedDepGraph>,
151152
prev_work_products: WorkProductMap,
152153
) -> Option<DepGraph> {
153154
if sess.opts.incremental.is_none() {

‎compiler/rustc_query_system/src/dep_graph/graph.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::fmt::Debug;
1414
use std::hash::Hash;
1515
use std::marker::PhantomData;
1616
use std::sync::atomic::Ordering;
17+
use std::sync::Arc;
1718

1819
use super::query::DepGraphQuery;
1920
use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex};
@@ -82,7 +83,7 @@ pub(crate) struct DepGraphData<D: Deps> {
8283

8384
/// The dep-graph from the previous compilation session. It contains all
8485
/// nodes and edges as well as all fingerprints of nodes that have them.
85-
previous: SerializedDepGraph,
86+
previous: Arc<SerializedDepGraph>,
8687

8788
colors: DepNodeColorMap,
8889

@@ -114,7 +115,7 @@ where
114115
impl<D: Deps> DepGraph<D> {
115116
pub fn new(
116117
profiler: &SelfProfilerRef,
117-
prev_graph: SerializedDepGraph,
118+
prev_graph: Arc<SerializedDepGraph>,
118119
prev_work_products: WorkProductMap,
119120
encoder: FileEncoder,
120121
record_graph: bool,

‎compiler/rustc_query_system/src/dep_graph/serialized.rs

Lines changed: 113 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,14 @@ use rustc_data_structures::fx::FxHashMap;
4444
use rustc_data_structures::profiling::SelfProfilerRef;
4545
use rustc_data_structures::sync::Lock;
4646
use rustc_data_structures::unhash::UnhashMap;
47+
use rustc_data_structures::{jobserver, outline};
4748
use rustc_index::{Idx, IndexVec};
4849
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
4950
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
50-
use std::iter;
51+
use rustc_session::Session;
5152
use 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`,
@@ -70,23 +73,47 @@ const DEP_NODE_PAD: usize = DEP_NODE_SIZE - 1;
7073
const DEP_NODE_WIDTH_BITS: usize = DEP_NODE_SIZE / 2;
7174

7275
/// Data for use when recompiling the **current crate**.
73-
#[derive(Debug, Default)]
7476
pub struct SerializedDepGraph {
7577
/// The set of all DepNodes in the graph
7678
nodes: IndexVec<SerializedDepNodeIndex, DepNode>,
79+
7780
/// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
7881
/// the DepNode at the same index in the nodes vector.
7982
fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
83+
8084
/// For each DepNode, stores the list of edges originating from that
8185
/// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
8286
/// which holds the actual DepNodeIndices of the target nodes.
8387
edge_list_indices: IndexVec<SerializedDepNodeIndex, EdgeHeader>,
88+
8489
/// A flattened list of all edge targets in the graph, stored in the same
8590
/// varint encoding that we use on disk. Edge sources are implicit in edge_list_indices.
8691
edge_list_data: Vec<u8>,
92+
8793
/// Stores a map from fingerprints to nodes per dep node kind.
88-
/// This is the reciprocal of `nodes`.
89-
index: Vec<UnhashMap<PackedFingerprint, SerializedDepNodeIndex>>,
94+
/// This is the reciprocal of `nodes`. This is computed on demand for each dep kind.
95+
/// The entire index is also computed in a background thread.
96+
index: Vec<OnceLock<UnhashMap<PackedFingerprint, SerializedDepNodeIndex>>>,
97+
98+
/// Stores the number of node for each dep node kind.
99+
index_sizes: Vec<usize>,
100+
101+
/// A profiler reference for used in the index prefetching thread.
102+
prof: SelfProfilerRef,
103+
}
104+
105+
impl Default for SerializedDepGraph {
106+
fn default() -> Self {
107+
SerializedDepGraph {
108+
nodes: Default::default(),
109+
fingerprints: Default::default(),
110+
edge_list_indices: Default::default(),
111+
edge_list_data: Default::default(),
112+
index: Default::default(),
113+
index_sizes: Default::default(),
114+
prof: SelfProfilerRef::new(None, None),
115+
}
116+
}
90117
}
91118

92119
impl SerializedDepGraph {
@@ -127,9 +154,35 @@ impl SerializedDepGraph {
127154
self.nodes[dep_node_index]
128155
}
129156

157+
/// This computes and sets up the index for just the specified `DepKind`.
158+
fn setup_index(&self, dep_kind: DepKind) {
159+
let _timer = self.prof.generic_activity("incr_comp_dep_graph_setup_index");
160+
161+
let mut index = UnhashMap::with_capacity_and_hasher(
162+
self.index_sizes[dep_kind.as_usize()],
163+
Default::default(),
164+
);
165+
166+
for (idx, node) in self.nodes.iter_enumerated() {
167+
if node.kind == dep_kind {
168+
index.insert(node.hash, idx);
169+
}
170+
}
171+
172+
// This may race with the prefetching thread, but that will set the same value.
173+
self.index[dep_kind.as_usize()].set(index).ok();
174+
}
175+
130176
#[inline]
131177
pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option<SerializedDepNodeIndex> {
132-
self.index.get(dep_node.kind.as_usize())?.get(&dep_node.hash).cloned()
178+
let index = self.index.get(dep_node.kind.as_usize())?;
179+
let index = index.get().unwrap_or_else(|| {
180+
outline(|| {
181+
self.setup_index(dep_node.kind);
182+
self.index[dep_node.kind.as_usize()].get().unwrap()
183+
})
184+
});
185+
index.get(&dep_node.hash).cloned()
133186
}
134187

135188
#[inline]
@@ -141,6 +194,44 @@ impl SerializedDepGraph {
141194
pub fn node_count(&self) -> usize {
142195
self.nodes.len()
143196
}
197+
198+
fn prefetch(&self) {
199+
let _timer = self.prof.generic_activity("incr_comp_prefetch_dep_graph_index");
200+
201+
let mut index: Vec<_> = self
202+
.index_sizes
203+
.iter()
204+
.map(|&n| UnhashMap::with_capacity_and_hasher(n, Default::default()))
205+
.collect();
206+
207+
for (idx, node) in self.nodes.iter_enumerated() {
208+
index[node.kind.as_usize()].insert(node.hash, idx);
209+
}
210+
211+
for (i, index) in index.into_iter().enumerate() {
212+
// This may race with `setup_index`, but that will set the same value.
213+
self.index[i].set(index).ok();
214+
}
215+
}
216+
217+
/// This spawns a thread that prefetches the index.
218+
fn spawn_prefetch_thread(self: &Arc<Self>) {
219+
if !self.index.is_empty() {
220+
let client = jobserver::client();
221+
if let Ok(true) = client.available().map(|tokens| tokens > 0) {
222+
if let Ok(token) = client.acquire() {
223+
let this = self.clone();
224+
thread::spawn(move || {
225+
this.prefetch();
226+
});
227+
return;
228+
}
229+
}
230+
231+
// Prefetch the index on the current thread if we don't have a token available.
232+
self.prefetch();
233+
}
234+
}
144235
}
145236

146237
/// A packed representation of an edge's start index and byte width.
@@ -175,8 +266,8 @@ fn mask(bits: usize) -> usize {
175266
}
176267

177268
impl SerializedDepGraph {
178-
#[instrument(level = "debug", skip(d))]
179-
pub fn decode<D: Deps>(d: &mut MemDecoder<'_>) -> SerializedDepGraph {
269+
#[instrument(level = "debug", skip(d, sess))]
270+
pub fn decode<D: Deps>(d: &mut MemDecoder<'_>,sess:&Session) -> Arc<SerializedDepGraph> {
180271
// The last 16 bytes are the node count and edge count.
181272
debug!("position: {:?}", d.position());
182273
let (node_count, edge_count) =
@@ -243,16 +334,21 @@ impl SerializedDepGraph {
243334
// end of the array. This padding ensure it doesn't.
244335
edge_list_data.extend(&[0u8; DEP_NODE_PAD]);
245336

246-
// Read the number of each dep kind and use it to create an hash map with a suitable size.
247-
let mut index: Vec<_> = (0..(D::DEP_KIND_MAX + 1))
248-
.map(|_| UnhashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default()))
249-
.collect();
250-
251-
for (idx, node) in nodes.iter_enumerated() {
252-
index[node.kind.as_usize()].insert(node.hash, idx);
253-
}
254-
255-
SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data, index }
337+
// Read the number of nodes for each dep kind.
338+
let index_sizes: Vec<_> =
339+
(0..(D::DEP_KIND_MAX + 1)).map(|_| d.read_u32() as usize).collect();
340+
341+
let result = Arc::new(SerializedDepGraph {
342+
nodes,
343+
fingerprints,
344+
edge_list_indices,
345+
edge_list_data,
346+
index: (0..index_sizes.len()).map(|_| OnceLock::new()).collect(),
347+
index_sizes,
348+
prof: sess.prof.clone(),
349+
});
350+
result.prefetch();
351+
result
256352
}
257353
}
258354

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /