Skip to content

Commit fcd003f

Browse files
committed
Use a sharded structure for the dep node index to dep node data map
1 parent b424c09 commit fcd003f

File tree

2 files changed

+88
-22
lines changed

2 files changed

+88
-22
lines changed

src/librustc/dep_graph/graph.rs

+83-22
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
33
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
44
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
55
use smallvec::SmallVec;
6-
use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicU64, Ordering};
6+
use rustc_data_structures::sync::{
7+
Lrc, Lock, LockGuard, MappedLockGuard, AtomicU32, AtomicU64, Ordering
8+
};
79
use rustc_data_structures::sharded::{self, Sharded};
810
use std::sync::atomic::Ordering::{Acquire, SeqCst};
911
use std::env;
12+
use std::iter;
1013
use std::hash::Hash;
14+
use std::convert::TryFrom;
1115
use std::collections::hash_map::Entry;
1216
use std::mem;
1317
use crate::ty::{self, TyCtxt};
@@ -124,7 +128,15 @@ impl DepGraph {
124128
}
125129

126130
pub fn query(&self) -> DepGraphQuery {
127-
let data = self.data.as_ref().unwrap().current.data.lock();
131+
let current = &self.data.as_ref().unwrap().current;
132+
let shards = current.data.lock_shards();
133+
let node_count = current.node_count.load(Acquire) as usize;
134+
let data: IndexVec<DepNodeIndex, _> = (0..node_count).map(|i| {
135+
let shard = i % sharded::SHARDS;
136+
let inner = i / sharded::SHARDS;
137+
&shards[shard][inner]
138+
}).collect();
139+
128140
let nodes: Vec<_> = data.iter().map(|n| n.node).collect();
129141
let mut edges = Vec::new();
130142
for (from, edge_targets) in data.iter()
@@ -442,8 +454,7 @@ impl DepGraph {
442454

443455
#[inline]
444456
pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
445-
let data = self.data.as_ref().expect("dep graph enabled").current.data.lock();
446-
data[dep_node_index].fingerprint
457+
self.data.as_ref().expect("dep graph enabled").current.data(dep_node_index).fingerprint
447458
}
448459

449460
pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
@@ -507,25 +518,32 @@ impl DepGraph {
507518
}
508519

509520
pub fn serialize(&self) -> SerializedDepGraph {
510-
let data = self.data.as_ref().unwrap().current.data.lock();
521+
let current = &self.data.as_ref().unwrap().current;
522+
let shards = current.data.lock_shards();
523+
let node_count = current.node_count.load(Acquire) as usize;
524+
let data = || (0..node_count).map(|i| {
525+
let shard = i % sharded::SHARDS;
526+
let inner = i / sharded::SHARDS;
527+
&shards[shard][inner]
528+
});
511529

512530
let fingerprints: IndexVec<SerializedDepNodeIndex, _> =
513-
data.iter().map(|d| d.fingerprint).collect();
531+
data().map(|d| d.fingerprint).collect();
514532
let nodes: IndexVec<SerializedDepNodeIndex, _> =
515-
data.iter().map(|d| d.node).collect();
533+
data().map(|d| d.node).collect();
516534

517-
let total_edge_count: usize = data.iter().map(|d| d.edges.len()).sum();
535+
let total_edge_count: usize = data().map(|d| d.edges.len()).sum();
518536

519537
let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
520538
let mut edge_list_data = Vec::with_capacity(total_edge_count);
521539

522-
for (current_dep_node_index, edges) in data.iter_enumerated().map(|(i, d)| (i, &d.edges)) {
540+
for (current_dep_node_index, edges) in data().enumerate().map(|(i, d)| (i, &d.edges)) {
523541
let start = edge_list_data.len() as u32;
524542
// This should really just be a memcpy :/
525543
edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index())));
526544
let end = edge_list_data.len() as u32;
527545

528-
debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len());
546+
debug_assert_eq!(current_dep_node_index, edge_list_indices.len());
529547
edge_list_indices.push((start, end));
530548
}
531549

@@ -964,7 +982,14 @@ struct DepNodeData {
964982
}
965983

966984
pub(super) struct CurrentDepGraph {
967-
data: Lock<IndexVec<DepNodeIndex, DepNodeData>>,
985+
/// The current node count. Used to allocate an index before storing it in the
986+
/// `data` and `node_to_node_index` field below.
987+
node_count: AtomicU64,
988+
989+
/// Maps from a `DepNodeIndex` to `DepNodeData`. The lowest bits of `DepNodeIndex` determines
990+
/// which shard is used and the higher bits are the index into the vector.
991+
data: Sharded<Vec<DepNodeData>>,
992+
968993
node_to_node_index: Sharded<FxHashMap<DepNode, DepNodeIndex>>,
969994
#[allow(dead_code)]
970995
forbidden_edge: Option<EdgeFilter>,
@@ -1017,7 +1042,8 @@ impl CurrentDepGraph {
10171042
let new_node_count_estimate = (prev_graph_node_count * 102) / 100 + 200;
10181043

10191044
CurrentDepGraph {
1020-
data: Lock::new(IndexVec::with_capacity(new_node_count_estimate)),
1045+
node_count: AtomicU64::new(0),
1046+
data: Sharded::new(|| Vec::with_capacity(new_node_count_estimate / sharded::SHARDS)),
10211047
node_to_node_index: Sharded::new(|| FxHashMap::with_capacity_and_hasher(
10221048
new_node_count_estimate / sharded::SHARDS,
10231049
Default::default(),
@@ -1081,20 +1107,56 @@ impl CurrentDepGraph {
10811107
edges: SmallVec<[DepNodeIndex; 8]>,
10821108
fingerprint: Fingerprint
10831109
) -> DepNodeIndex {
1084-
match self.node_to_node_index.get_shard_by_value(&dep_node).lock().entry(dep_node) {
1110+
let (index, inserted) = match self.node_to_node_index
1111+
.get_shard_by_value(&dep_node)
1112+
.lock()
1113+
.entry(dep_node) {
10851114
Entry::Occupied(entry) => *entry.get(),
10861115
Entry::Vacant(entry) => {
1087-
let mut data = self.data.lock();
1088-
let dep_node_index = DepNodeIndex::new(data.len());
1089-
data.push(DepNodeData {
1090-
node: dep_node,
1091-
edges,
1092-
fingerprint
1093-
});
1116+
let index = self.node_count.fetch_add(1, SeqCst);
1117+
// Cast to u32 to ensure we didn't overflow.
1118+
let index = u32::try_from(index).unwrap();
1119+
1120+
let dep_node_index = DepNodeIndex::new(index as usize);
10941121
entry.insert(dep_node_index);
10951122
dep_node_index
10961123
}
1124+
};
1125+
1126+
if inserted {
1127+
let dep_node_data = DepNodeData {
1128+
node: dep_node,
1129+
edges,
1130+
fingerprint
1131+
};
1132+
let inner_index = index.as_usize() / sharded::SHARDS;
1133+
let mut data = self.data.get_shard_by_index(index.as_usize()).lock();
1134+
let len = data.len();
1135+
if likely!(len == inner_index) {
1136+
data.push(dep_node_data)
1137+
} else {
1138+
let dummy_data = DepNodeData {
1139+
node: DepNode::new_no_params(DepKind::Null),
1140+
edges: SmallVec::default(),
1141+
fingerprint: Fingerprint::ZERO,
1142+
};
1143+
if inner_index >= len {
1144+
data.extend(iter::repeat(dummy_data).take(inner_index - len + 1));
1145+
}
1146+
data[inner_index] = dep_node_data;
1147+
}
10971148
}
1149+
1150+
(index, inserted)
1151+
}
1152+
1153+
fn data(
1154+
&self,
1155+
index: DepNodeIndex,
1156+
) -> MappedLockGuard<'_, DepNodeData> {
1157+
LockGuard::map(self.data.get_shard_by_index(index.as_usize()).lock(), |vec| {
1158+
&mut vec[index.as_usize() / sharded::SHARDS]
1159+
})
10981160
}
10991161
}
11001162

@@ -1113,9 +1175,8 @@ impl DepGraphData {
11131175
#[cfg(debug_assertions)]
11141176
{
11151177
if let Some(target) = task_deps.node {
1116-
let data = self.current.data.lock();
11171178
if let Some(ref forbidden_edge) = self.current.forbidden_edge {
1118-
let source = data[source].node;
1179+
let source = self.current.data(source).node;
11191180
if forbidden_edge.test(&source, &target) {
11201181
bug!("forbidden edge {:?} -> {:?} created",
11211182
source,

src/librustc_data_structures/sharded.rs

+5
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ impl<T> Sharded<T> {
5757
}
5858
}
5959

60+
#[inline]
61+
pub fn get_shard_by_index(&self, index: usize) -> &Lock<T> {
62+
&self.shards[index % SHARDS].0
63+
}
64+
6065
#[inline]
6166
pub fn get_shard_by_value<K: Hash + ?Sized>(&self, val: &K) -> &Lock<T> {
6267
if SHARDS == 1 {

0 commit comments

Comments
 (0)