Skip to content

Commit 3b1fe7e

Browse files
committed
Auto merge of #94084 - Mark-Simulacrum:drop-sharded, r=cjgillot
Avoid query cache sharding code in single-threaded mode In non-parallel compilers, this is just adding needless overhead at compilation time (since there is only one shard statically anyway). This amounts to roughly ~10 seconds reduction in bootstrap time, with overall neutral (some wins, some losses) performance results. Parallel compiler performance should be largely unaffected by this PR; sharding is kept there.
2 parents bab4c13 + 594ea74 commit 3b1fe7e

File tree

8 files changed

+167
-204
lines changed

8 files changed

+167
-204
lines changed

compiler/rustc_data_structures/src/sharded.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> {
129129
}
130130

131131
#[inline]
132-
fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
132+
pub fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
133133
let mut state = FxHasher::default();
134134
val.hash(&mut state);
135135
state.finish()

compiler/rustc_middle/src/ty/query.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ macro_rules! define_callbacks {
210210

211211
#[derive(Default)]
212212
pub struct QueryCaches<$tcx> {
213-
$($(#[$attr])* pub $name: QueryCacheStore<query_storage::$name<$tcx>>,)*
213+
$($(#[$attr])* pub $name: query_storage::$name<$tcx>,)*
214214
}
215215

216216
impl<$tcx> TyCtxtEnsure<$tcx> {
@@ -222,12 +222,12 @@ macro_rules! define_callbacks {
222222

223223
let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
224224

225-
let lookup = match cached {
225+
match cached {
226226
Ok(()) => return,
227-
Err(lookup) => lookup,
228-
};
227+
Err(()) => (),
228+
}
229229

230-
self.tcx.queries.$name(self.tcx, DUMMY_SP, key, lookup, QueryMode::Ensure);
230+
self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure);
231231
})*
232232
}
233233

@@ -251,12 +251,12 @@ macro_rules! define_callbacks {
251251

252252
let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy);
253253

254-
let lookup = match cached {
254+
match cached {
255255
Ok(value) => return value,
256-
Err(lookup) => lookup,
257-
};
256+
Err(()) => (),
257+
}
258258

259-
self.tcx.queries.$name(self.tcx, self.span, key, lookup, QueryMode::Get).unwrap()
259+
self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap()
260260
})*
261261
}
262262

@@ -314,7 +314,6 @@ macro_rules! define_callbacks {
314314
tcx: TyCtxt<$tcx>,
315315
span: Span,
316316
key: query_keys::$name<$tcx>,
317-
lookup: QueryLookup,
318317
mode: QueryMode,
319318
) -> Option<query_stored::$name<$tcx>>;)*
320319
}

compiler/rustc_query_impl/src/on_disk_cache.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_middle::thir;
1313
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
1414
use rustc_middle::ty::{self, Ty, TyCtxt};
1515
use rustc_query_system::dep_graph::DepContext;
16-
use rustc_query_system::query::{QueryContext, QuerySideEffects};
16+
use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects};
1717
use rustc_serialize::{
1818
opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
1919
Decodable, Decoder, Encodable, Encoder,
@@ -1034,7 +1034,7 @@ where
10341034
assert!(Q::query_state(tcx).all_inactive());
10351035
let cache = Q::query_cache(tcx);
10361036
let mut res = Ok(());
1037-
cache.iter_results(&mut |key, value, dep_node| {
1037+
cache.iter(&mut |key, value, dep_node| {
10381038
if res.is_err() {
10391039
return;
10401040
}

compiler/rustc_query_impl/src/plumbing.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ macro_rules! define_queries {
336336
}
337337

338338
#[inline(always)]
339-
fn query_cache<'a>(tcx: QueryCtxt<$tcx>) -> &'a QueryCacheStore<Self::Cache>
339+
fn query_cache<'a>(tcx: QueryCtxt<$tcx>) -> &'a Self::Cache
340340
where 'tcx:'a
341341
{
342342
&tcx.query_caches.$name
@@ -537,12 +537,11 @@ macro_rules! define_queries_struct {
537537
tcx: TyCtxt<$tcx>,
538538
span: Span,
539539
key: query_keys::$name<$tcx>,
540-
lookup: QueryLookup,
541540
mode: QueryMode,
542541
) -> Option<query_stored::$name<$tcx>> {
543542
opt_remap_env_constness!([$($modifiers)*][key]);
544543
let qcx = QueryCtxt { tcx, queries: self };
545-
get_query::<queries::$name<$tcx>, _>(qcx, span, key, lookup, mode)
544+
get_query::<queries::$name<$tcx>, _>(qcx, span, key, mode)
546545
})*
547546
}
548547
};

compiler/rustc_query_impl/src/profiling_support.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_data_structures::profiling::SelfProfiler;
44
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
55
use rustc_hir::definitions::DefPathData;
66
use rustc_middle::ty::{TyCtxt, WithOptConstParam};
7-
use rustc_query_system::query::{QueryCache, QueryCacheStore};
7+
use rustc_query_system::query::QueryCache;
88
use std::fmt::Debug;
99
use std::io::Write;
1010

@@ -229,7 +229,7 @@ where
229229
fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
230230
tcx: TyCtxt<'tcx>,
231231
query_name: &'static str,
232-
query_cache: &QueryCacheStore<C>,
232+
query_cache: &C,
233233
string_cache: &mut QueryKeyStringCache,
234234
) where
235235
C: QueryCache,
@@ -251,7 +251,7 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
251251
// locked while doing so. Instead we copy out the
252252
// `(query_key, dep_node_index)` pairs and release the lock again.
253253
let mut query_keys_and_indices = Vec::new();
254-
query_cache.iter_results(&mut |k, _, i| query_keys_and_indices.push((k.clone(), i)));
254+
query_cache.iter(&mut |k, _, i| query_keys_and_indices.push((k.clone(), i)));
255255

256256
// Now actually allocate the strings. If allocating the strings
257257
// generates new entries in the query cache, we'll miss them but
@@ -276,7 +276,7 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
276276
let event_id = event_id_builder.from_label(query_name).to_string_id();
277277

278278
let mut query_invocation_ids = Vec::new();
279-
query_cache.iter_results(&mut |_, _, i| {
279+
query_cache.iter(&mut |_, _, i| {
280280
query_invocation_ids.push(i.into());
281281
});
282282

compiler/rustc_query_system/src/query/caches.rs

+76-73
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use crate::dep_graph::DepNodeIndex;
2-
use crate::query::plumbing::{QueryCacheStore, QueryLookup};
32

43
use rustc_arena::TypedArena;
54
use rustc_data_structures::fx::FxHashMap;
5+
use rustc_data_structures::sharded;
6+
#[cfg(parallel_compiler)]
67
use rustc_data_structures::sharded::Sharded;
8+
#[cfg(not(parallel_compiler))]
9+
use rustc_data_structures::sync::Lock;
710
use rustc_data_structures::sync::WorkerLocal;
811
use std::default::Default;
912
use std::fmt::Debug;
@@ -25,35 +28,23 @@ pub trait QueryStorage {
2528

2629
pub trait QueryCache: QueryStorage + Sized {
2730
type Key: Hash + Eq + Clone + Debug;
28-
type Sharded: Default;
2931

3032
/// Checks if the query is already computed and in the cache.
3133
/// It returns the shard index and a lock guard to the shard,
3234
/// which will be used if the query is not in the cache and we need
3335
/// to compute it.
34-
fn lookup<'s, R, OnHit>(
36+
fn lookup<R, OnHit>(
3537
&self,
36-
state: &'s QueryCacheStore<Self>,
3738
key: &Self::Key,
3839
// `on_hit` can be called while holding a lock to the query state shard.
3940
on_hit: OnHit,
40-
) -> Result<R, QueryLookup>
41+
) -> Result<R, ()>
4142
where
4243
OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R;
4344

44-
fn complete(
45-
&self,
46-
lock_sharded_storage: &mut Self::Sharded,
47-
key: Self::Key,
48-
value: Self::Value,
49-
index: DepNodeIndex,
50-
) -> Self::Stored;
45+
fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex) -> Self::Stored;
5146

52-
fn iter(
53-
&self,
54-
shards: &Sharded<Self::Sharded>,
55-
f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex),
56-
);
47+
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex));
5748
}
5849

5950
pub struct DefaultCacheSelector;
@@ -62,11 +53,16 @@ impl<K: Eq + Hash, V: Clone> CacheSelector<K, V> for DefaultCacheSelector {
6253
type Cache = DefaultCache<K, V>;
6354
}
6455

65-
pub struct DefaultCache<K, V>(PhantomData<(K, V)>);
56+
pub struct DefaultCache<K, V> {
57+
#[cfg(parallel_compiler)]
58+
cache: Sharded<FxHashMap<K, (V, DepNodeIndex)>>,
59+
#[cfg(not(parallel_compiler))]
60+
cache: Lock<FxHashMap<K, (V, DepNodeIndex)>>,
61+
}
6662

6763
impl<K, V> Default for DefaultCache<K, V> {
6864
fn default() -> Self {
69-
DefaultCache(PhantomData)
65+
DefaultCache { cache: Default::default() }
7066
}
7167
}
7268

@@ -87,49 +83,51 @@ where
8783
V: Clone + Debug,
8884
{
8985
type Key = K;
90-
type Sharded = FxHashMap<K, (V, DepNodeIndex)>;
9186

9287
#[inline(always)]
93-
fn lookup<'s, R, OnHit>(
94-
&self,
95-
state: &'s QueryCacheStore<Self>,
96-
key: &K,
97-
on_hit: OnHit,
98-
) -> Result<R, QueryLookup>
88+
fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
9989
where
10090
OnHit: FnOnce(&V, DepNodeIndex) -> R,
10191
{
102-
let (lookup, lock) = state.get_lookup(key);
103-
let result = lock.raw_entry().from_key_hashed_nocheck(lookup.key_hash, key);
92+
let key_hash = sharded::make_hash(key);
93+
#[cfg(parallel_compiler)]
94+
let lock = self.cache.get_shard_by_hash(key_hash).lock();
95+
#[cfg(not(parallel_compiler))]
96+
let lock = self.cache.lock();
97+
let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
10498

10599
if let Some((_, value)) = result {
106100
let hit_result = on_hit(&value.0, value.1);
107101
Ok(hit_result)
108102
} else {
109-
Err(lookup)
103+
Err(())
110104
}
111105
}
112106

113107
#[inline]
114-
fn complete(
115-
&self,
116-
lock_sharded_storage: &mut Self::Sharded,
117-
key: K,
118-
value: V,
119-
index: DepNodeIndex,
120-
) -> Self::Stored {
121-
lock_sharded_storage.insert(key, (value.clone(), index));
108+
fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
109+
#[cfg(parallel_compiler)]
110+
let mut lock = self.cache.get_shard_by_value(&key).lock();
111+
#[cfg(not(parallel_compiler))]
112+
let mut lock = self.cache.lock();
113+
lock.insert(key, (value.clone(), index));
122114
value
123115
}
124116

125-
fn iter(
126-
&self,
127-
shards: &Sharded<Self::Sharded>,
128-
f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex),
129-
) {
130-
let shards = shards.lock_shards();
131-
for shard in shards.iter() {
132-
for (k, v) in shard.iter() {
117+
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
118+
#[cfg(parallel_compiler)]
119+
{
120+
let shards = self.cache.lock_shards();
121+
for shard in shards.iter() {
122+
for (k, v) in shard.iter() {
123+
f(k, &v.0, v.1);
124+
}
125+
}
126+
}
127+
#[cfg(not(parallel_compiler))]
128+
{
129+
let map = self.cache.lock();
130+
for (k, v) in map.iter() {
133131
f(k, &v.0, v.1);
134132
}
135133
}
@@ -144,12 +142,15 @@ impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<K, V> for ArenaCacheSelector<'tc
144142

145143
pub struct ArenaCache<'tcx, K, V> {
146144
arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
147-
phantom: PhantomData<(K, &'tcx V)>,
145+
#[cfg(parallel_compiler)]
146+
cache: Sharded<FxHashMap<K, &'tcx (V, DepNodeIndex)>>,
147+
#[cfg(not(parallel_compiler))]
148+
cache: Lock<FxHashMap<K, &'tcx (V, DepNodeIndex)>>,
148149
}
149150

150151
impl<'tcx, K, V> Default for ArenaCache<'tcx, K, V> {
151152
fn default() -> Self {
152-
ArenaCache { arena: WorkerLocal::new(|_| TypedArena::default()), phantom: PhantomData }
153+
ArenaCache { arena: WorkerLocal::new(|_| TypedArena::default()), cache: Default::default() }
153154
}
154155
}
155156

@@ -171,51 +172,53 @@ where
171172
V: Debug,
172173
{
173174
type Key = K;
174-
type Sharded = FxHashMap<K, &'tcx (V, DepNodeIndex)>;
175175

176176
#[inline(always)]
177-
fn lookup<'s, R, OnHit>(
178-
&self,
179-
state: &'s QueryCacheStore<Self>,
180-
key: &K,
181-
on_hit: OnHit,
182-
) -> Result<R, QueryLookup>
177+
fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
183178
where
184179
OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
185180
{
186-
let (lookup, lock) = state.get_lookup(key);
187-
let result = lock.raw_entry().from_key_hashed_nocheck(lookup.key_hash, key);
181+
let key_hash = sharded::make_hash(key);
182+
#[cfg(parallel_compiler)]
183+
let lock = self.cache.get_shard_by_hash(key_hash).lock();
184+
#[cfg(not(parallel_compiler))]
185+
let lock = self.cache.lock();
186+
let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
188187

189188
if let Some((_, value)) = result {
190189
let hit_result = on_hit(&&value.0, value.1);
191190
Ok(hit_result)
192191
} else {
193-
Err(lookup)
192+
Err(())
194193
}
195194
}
196195

197196
#[inline]
198-
fn complete(
199-
&self,
200-
lock_sharded_storage: &mut Self::Sharded,
201-
key: K,
202-
value: V,
203-
index: DepNodeIndex,
204-
) -> Self::Stored {
197+
fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
205198
let value = self.arena.alloc((value, index));
206199
let value = unsafe { &*(value as *const _) };
207-
lock_sharded_storage.insert(key, value);
200+
#[cfg(parallel_compiler)]
201+
let mut lock = self.cache.get_shard_by_value(&key).lock();
202+
#[cfg(not(parallel_compiler))]
203+
let mut lock = self.cache.lock();
204+
lock.insert(key, value);
208205
&value.0
209206
}
210207

211-
fn iter(
212-
&self,
213-
shards: &Sharded<Self::Sharded>,
214-
f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex),
215-
) {
216-
let shards = shards.lock_shards();
217-
for shard in shards.iter() {
218-
for (k, v) in shard.iter() {
208+
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
209+
#[cfg(parallel_compiler)]
210+
{
211+
let shards = self.cache.lock_shards();
212+
for shard in shards.iter() {
213+
for (k, v) in shard.iter() {
214+
f(k, &v.0, v.1);
215+
}
216+
}
217+
}
218+
#[cfg(not(parallel_compiler))]
219+
{
220+
let map = self.cache.lock();
221+
for (k, v) in map.iter() {
219222
f(k, &v.0, v.1);
220223
}
221224
}

0 commit comments

Comments
 (0)