Skip to content

Commit f583513

Browse files
committed
Intorduced MiniMap - a tiny small storage optimized map implementation
This makes everything about 1% faster in rustc-perf, mostly negating performance hit of previous commit.
1 parent 17d2e3b commit f583513

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3594,6 +3594,7 @@ dependencies = [
35943594
name = "rustc_infer"
35953595
version = "0.0.0"
35963596
dependencies = [
3597+
"arrayvec",
35973598
"rustc_ast",
35983599
"rustc_data_structures",
35993600
"rustc_errors",

compiler/rustc_infer/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ rustc_serialize = { path = "../rustc_serialize" }
2121
rustc_span = { path = "../rustc_span" }
2222
rustc_target = { path = "../rustc_target" }
2323
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
24+
arrayvec = { version = "0.5.1", default-features = false }
2425
rustc_ast = { path = "../rustc_ast" }

compiler/rustc_infer/src/infer/combine.rs

+61-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ use super::unify_key::replace_if_possible;
3131
use super::unify_key::{ConstVarValue, ConstVariableValue};
3232
use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
3333
use super::{InferCtxt, MiscVariable, TypeTrace};
34+
use arrayvec::ArrayVec;
3435
use rustc_data_structures::fx::FxHashMap;
36+
use std::hash::Hash;
3537

3638
use crate::traits::{Obligation, PredicateObligations};
3739

@@ -45,6 +47,63 @@ use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
4547
use rustc_middle::ty::{IntType, UintType};
4648
use rustc_span::DUMMY_SP;
4749

50+
/// Small-storage-optimized implementation of a map
51+
/// made specifically for caching results.
52+
///
53+
/// Stores elements in a small array up to a certain length
54+
/// and switches to `HashMap` when that length is exceeded.
55+
enum MiniMap<K, V> {
56+
Array(ArrayVec<[(K, V); 8]>),
57+
Map(FxHashMap<K, V>),
58+
}
59+
60+
impl<K: Eq + Hash, V> MiniMap<K, V> {
61+
/// Creates an empty `MiniMap`.
62+
pub fn new() -> Self {
63+
MiniMap::Array(ArrayVec::new())
64+
}
65+
66+
/// Inserts or updates value in the map.
67+
pub fn insert(&mut self, key: K, value: V) {
68+
match self {
69+
MiniMap::Array(array) => {
70+
for pair in array.iter_mut() {
71+
if pair.0 == key {
72+
pair.1 = value;
73+
return;
74+
}
75+
}
76+
if let Err(error) = array.try_push((key, value)) {
77+
let mut map: FxHashMap<K, V> = array.drain(..).collect();
78+
let (key, value) = error.element();
79+
map.insert(key, value);
80+
*self = MiniMap::Map(map);
81+
}
82+
}
83+
MiniMap::Map(map) => {
84+
map.insert(key, value);
85+
}
86+
}
87+
}
88+
89+
/// Return value by key if any.
90+
pub fn get(&self, key: &K) -> Option<&V> {
91+
match self {
92+
MiniMap::Array(array) => {
93+
for pair in array {
94+
if pair.0 == *key {
95+
return Some(&pair.1);
96+
}
97+
}
98+
return None;
99+
}
100+
MiniMap::Map(map) => {
101+
return map.get(key);
102+
}
103+
}
104+
}
105+
}
106+
48107
#[derive(Clone)]
49108
pub struct CombineFields<'infcx, 'tcx> {
50109
pub infcx: &'infcx InferCtxt<'infcx, 'tcx>,
@@ -380,7 +439,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
380439
needs_wf: false,
381440
root_ty: ty,
382441
param_env: self.param_env,
383-
cache: FxHashMap::default(),
442+
cache: MiniMap::new(),
384443
};
385444

386445
let ty = match generalize.relate(ty, ty) {
@@ -441,7 +500,7 @@ struct Generalizer<'cx, 'tcx> {
441500

442501
param_env: ty::ParamEnv<'tcx>,
443502

444-
cache: FxHashMap<(Ty<'tcx>, Ty<'tcx>), RelateResult<'tcx, Ty<'tcx>>>,
503+
cache: MiniMap<(Ty<'tcx>, Ty<'tcx>), RelateResult<'tcx, Ty<'tcx>>>,
445504
}
446505

447506
/// Result from a generalization operation. This includes

0 commit comments

Comments
 (0)