Skip to content

Commit 9b89036

Browse files
committed
Auto merge of #66013 - nnethercote:avoid-hashing-twice-in-get_query, r=<try>
Avoid hashing the key twice in `get_query()`. For a single-threaded parallel compiler, this reduces instruction counts across several benchmarks, by up to 2.8%. The commit also adds documentation about `Sharded`'s use of `FxHasher`. r? @Zoxc
2 parents aa4e57c + 6fb6a7b commit 9b89036

File tree

3 files changed

+17
-3
lines changed

3 files changed

+17
-3
lines changed

src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#![feature(log_syntax)]
6262
#![feature(associated_type_bounds)]
6363
#![feature(rustc_attrs)]
64+
#![feature(hash_raw_entry)]
6465

6566
#![recursion_limit="512"]
6667

src/librustc/ty/query/plumbing.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ use errors::Level;
1414
use errors::Diagnostic;
1515
use errors::FatalError;
1616
use errors::Handler;
17-
use rustc_data_structures::fx::{FxHashMap};
17+
use rustc_data_structures::fx::{FxHasher, FxHashMap};
1818
use rustc_data_structures::sync::{Lrc, Lock};
1919
use rustc_data_structures::sharded::Sharded;
2020
use rustc_data_structures::thin_vec::ThinVec;
2121
#[cfg(not(parallel_compiler))]
2222
use rustc_data_structures::cold_path;
23+
use std::hash::{Hash, Hasher};
2324
use std::mem;
2425
use std::ptr;
2526
use std::collections::hash_map::Entry;
@@ -80,8 +81,17 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
8081
pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> {
8182
let cache = Q::query_cache(tcx);
8283
loop {
83-
let mut lock = cache.get_shard_by_value(key).lock();
84-
if let Some(value) = lock.results.get(key) {
84+
// We compute the key's hash once and then use it for both the
85+
// shard lookup and the hashmap lookup. This relies on the fact
86+
// that both of them use `FxHasher`.
87+
let mut state = FxHasher::default();
88+
key.hash(&mut state);
89+
let key_hash = state.finish();
90+
91+
let mut lock = cache.get_shard_by_hash(key_hash).lock();
92+
if let Some((_, value)) =
93+
lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key)
94+
{
8595
tcx.prof.query_cache_hit(Q::NAME);
8696
let result = (value.value.clone(), value.index);
8797
#[cfg(debug_assertions)]

src/librustc_data_structures/sharded.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const SHARD_BITS: usize = 0;
2222
pub const SHARDS: usize = 1 << SHARD_BITS;
2323

2424
/// An array of cache-line aligned inner locked structures with convenience methods.
25+
/// Shards are selected by hashing values with `FxHasher`.
2526
#[derive(Clone)]
2627
pub struct Sharded<T> {
2728
shards: [CacheAligned<Lock<T>>; SHARDS],
@@ -69,6 +70,8 @@ impl<T> Sharded<T> {
6970
}
7071
}
7172

73+
/// Get a shard with a pre-computed hash value, which must be computed by
74+
/// `FxHasher`.
7275
#[inline]
7376
pub fn get_shard_by_hash(&self, hash: u64) -> &Lock<T> {
7477
let hash_len = mem::size_of::<usize>();

0 commit comments

Comments
 (0)