Skip to content

Commit acb52ab

Browse files
authored
Rollup merge of rust-lang#65472 - Zoxc:sharded-dep-graph-2, r=nikomatsakis
Use a sharded dep node to dep node index map Split out from rust-lang#61845 and based on rust-lang#63756. r? @nikomatsakis
2 parents 49b5f0a + 42c0236 commit acb52ab

File tree

2 files changed

+44
-15
lines changed

2 files changed

+44
-15
lines changed

src/librustc/dep_graph/graph.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
44
use rustc_index::vec::{Idx, IndexVec};
55
use smallvec::SmallVec;
66
use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicU64, Ordering};
7+
use rustc_data_structures::sharded::{self, Sharded};
78
use std::sync::atomic::Ordering::SeqCst;
89
use std::env;
910
use std::hash::Hash;
@@ -381,7 +382,7 @@ impl DepGraph {
381382
#[inline]
382383
pub fn read(&self, v: DepNode) {
383384
if let Some(ref data) = self.data {
384-
let map = data.current.node_to_node_index.lock();
385+
let map = data.current.node_to_node_index.get_shard_by_value(&v).lock();
385386
if let Some(dep_node_index) = map.get(&v).copied() {
386387
std::mem::drop(map);
387388
data.read_index(dep_node_index);
@@ -405,6 +406,7 @@ impl DepGraph {
405406
.unwrap()
406407
.current
407408
.node_to_node_index
409+
.get_shard_by_value(dep_node)
408410
.lock()
409411
.get(dep_node)
410412
.cloned()
@@ -414,7 +416,11 @@ impl DepGraph {
414416
#[inline]
415417
pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool {
416418
if let Some(ref data) = self.data {
417-
data.current.node_to_node_index.lock().contains_key(dep_node)
419+
data.current
420+
.node_to_node_index
421+
.get_shard_by_value(&dep_node)
422+
.lock()
423+
.contains_key(dep_node)
418424
} else {
419425
false
420426
}
@@ -595,7 +601,11 @@ impl DepGraph {
595601

596602
#[cfg(not(parallel_compiler))]
597603
{
598-
debug_assert!(!data.current.node_to_node_index.lock().contains_key(dep_node));
604+
debug_assert!(!data.current
605+
.node_to_node_index
606+
.get_shard_by_value(dep_node)
607+
.lock()
608+
.contains_key(dep_node));
599609
debug_assert!(data.colors.get(prev_dep_node_index).is_none());
600610
}
601611

@@ -927,7 +937,7 @@ struct DepNodeData {
927937
/// acquire the lock on `data.`
928938
pub(super) struct CurrentDepGraph {
929939
data: Lock<IndexVec<DepNodeIndex, DepNodeData>>,
930-
node_to_node_index: Lock<FxHashMap<DepNode, DepNodeIndex>>,
940+
node_to_node_index: Sharded<FxHashMap<DepNode, DepNodeIndex>>,
931941

932942
/// Used to trap when a specific edge is added to the graph.
933943
/// This is used for debug purposes and is only active with `debug_assertions`.
@@ -985,8 +995,8 @@ impl CurrentDepGraph {
985995

986996
CurrentDepGraph {
987997
data: Lock::new(IndexVec::with_capacity(new_node_count_estimate)),
988-
node_to_node_index: Lock::new(FxHashMap::with_capacity_and_hasher(
989-
new_node_count_estimate,
998+
node_to_node_index: Sharded::new(|| FxHashMap::with_capacity_and_hasher(
999+
new_node_count_estimate / sharded::SHARDS,
9901000
Default::default(),
9911001
)),
9921002
anon_id_seed: stable_hasher.finish(),
@@ -1035,7 +1045,10 @@ impl CurrentDepGraph {
10351045
edges: SmallVec<[DepNodeIndex; 8]>,
10361046
fingerprint: Fingerprint
10371047
) -> DepNodeIndex {
1038-
debug_assert!(!self.node_to_node_index.lock().contains_key(&dep_node));
1048+
debug_assert!(!self.node_to_node_index
1049+
.get_shard_by_value(&dep_node)
1050+
.lock()
1051+
.contains_key(&dep_node));
10391052
self.intern_node(dep_node, edges, fingerprint)
10401053
}
10411054

@@ -1045,7 +1058,7 @@ impl CurrentDepGraph {
10451058
edges: SmallVec<[DepNodeIndex; 8]>,
10461059
fingerprint: Fingerprint
10471060
) -> DepNodeIndex {
1048-
match self.node_to_node_index.lock().entry(dep_node) {
1061+
match self.node_to_node_index.get_shard_by_value(&dep_node).lock().entry(dep_node) {
10491062
Entry::Occupied(entry) => *entry.get(),
10501063
Entry::Vacant(entry) => {
10511064
let mut data = self.data.lock();

src/librustc_data_structures/sharded.rs

+23-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::hash::{Hasher, Hash};
22
use std::mem;
33
use std::borrow::Borrow;
44
use std::collections::hash_map::RawEntryMut;
5+
use smallvec::SmallVec;
56
use crate::fx::{FxHasher, FxHashMap};
67
use crate::sync::{Lock, LockGuard};
78

@@ -18,7 +19,7 @@ const SHARD_BITS: usize = 5;
1819
#[cfg(not(parallel_compiler))]
1920
const SHARD_BITS: usize = 0;
2021

21-
const SHARDS: usize = 1 << SHARD_BITS;
22+
pub const SHARDS: usize = 1 << SHARD_BITS;
2223

2324
/// An array of cache-line aligned inner locked structures with convenience methods.
2425
#[derive(Clone)]
@@ -29,21 +30,36 @@ pub struct Sharded<T> {
2930
impl<T: Default> Default for Sharded<T> {
3031
#[inline]
3132
fn default() -> Self {
33+
Self::new(|| T::default())
34+
}
35+
}
36+
37+
impl<T> Sharded<T> {
38+
#[inline]
39+
pub fn new(mut value: impl FnMut() -> T) -> Self {
40+
// Create a vector of the values we want
41+
let mut values: SmallVec<[_; SHARDS]> = (0..SHARDS).map(|_| {
42+
CacheAligned(Lock::new(value()))
43+
}).collect();
44+
45+
// Create an unintialized array
3246
let mut shards: mem::MaybeUninit<[CacheAligned<Lock<T>>; SHARDS]> =
3347
mem::MaybeUninit::uninit();
34-
let first = shards.as_mut_ptr() as *mut CacheAligned<Lock<T>>;
48+
3549
unsafe {
36-
for i in 0..SHARDS {
37-
first.add(i).write(CacheAligned(Lock::new(T::default())));
38-
}
50+
// Copy the values into our array
51+
let first = shards.as_mut_ptr() as *mut CacheAligned<Lock<T>>;
52+
values.as_ptr().copy_to_nonoverlapping(first, SHARDS);
53+
54+
// Ignore the content of the vector
55+
values.set_len(0);
56+
3957
Sharded {
4058
shards: shards.assume_init(),
4159
}
4260
}
4361
}
44-
}
4562

46-
impl<T> Sharded<T> {
4763
#[inline]
4864
pub fn get_shard_by_value<K: Hash + ?Sized>(&self, val: &K) -> &Lock<T> {
4965
if SHARDS == 1 {

0 commit comments

Comments
 (0)