Skip to content

Commit c5e7aa9

Browse files
committed
Auto merge of rust-lang#137354 - FractalFir:intern_with_cap, r=<try>
[perf experiment] Changed interners to start preallocated with an increased capacity Inspired by rust-lang#137005. *Not meant to be merged in its current form* Added a `with_capacity` function to `InternedSet`. Changed the `CtxtInterners` to start with `InternedSets` preallocated with a capacity. This *does* increase memory usage at very slightly(by 1 MB at the start), altough that increase quickly disaperars for larger crates(since they require such capacity anyway). A local perf run indicates this improves compiletimes for small crates(like `ripgrep`), without a negative effect on larger ones: ![image](https://github.com/user-attachments/assets/4a7f3317-7e61-4b28-a651-cc79ee990689) The current default capacities are choosen somewhat arbitrarily, and are relatively low. Depending on what kind of memory usage is acceptable, it may be beneficial to increase that capacity for some interners. From a second local perf run(with capacity of `_type` increased to `131072`), it looks like increasing the size of the preallocated type interner has the biggest impact: ![image](https://github.com/user-attachments/assets/08ac324a-b03c-4fe9-b779-4dd35e7970d9) What would be the maximum acceptable memory usage increase? I think most people would not mind sacrificing 1-2MB for an improvement in compile speed, but I am curious what is the general opinion here.
2 parents 71e06b9 + 441f061 commit c5e7aa9

File tree

2 files changed

+44
-24
lines changed

2 files changed

+44
-24
lines changed

compiler/rustc_data_structures/src/sharded.rs

+3
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ pub fn shards() -> usize {
143143
pub type ShardedHashMap<K, V> = Sharded<FxHashMap<K, V>>;
144144

145145
impl<K: Eq, V> ShardedHashMap<K, V> {
146+
pub fn with_capacity(cap: usize) -> Self {
147+
Self::new(|| FxHashMap::with_capacity_and_hasher(cap, rustc_hash::FxBuildHasher::default()))
148+
}
146149
pub fn len(&self) -> usize {
147150
self.lock_shards().map(|shard| shard.len()).sum()
148151
}

compiler/rustc_middle/src/ty/context.rs

+41-24
Original file line numberDiff line numberDiff line change
@@ -814,30 +814,45 @@ impl<'tcx> CtxtInterners<'tcx> {
814814
fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
815815
CtxtInterners {
816816
arena,
817-
type_: Default::default(),
818-
const_lists: Default::default(),
819-
args: Default::default(),
820-
type_lists: Default::default(),
821-
region: Default::default(),
822-
poly_existential_predicates: Default::default(),
823-
canonical_var_infos: Default::default(),
824-
predicate: Default::default(),
825-
clauses: Default::default(),
826-
projs: Default::default(),
827-
place_elems: Default::default(),
828-
const_: Default::default(),
829-
pat: Default::default(),
830-
const_allocation: Default::default(),
831-
bound_variable_kinds: Default::default(),
832-
layout: Default::default(),
833-
adt_def: Default::default(),
834-
external_constraints: Default::default(),
835-
predefined_opaques_in_body: Default::default(),
836-
fields: Default::default(),
837-
local_def_ids: Default::default(),
838-
captures: Default::default(),
839-
offset_of: Default::default(),
840-
valtree: Default::default(),
817+
// From some experiments, it looks like there usualy are < 2^20 types.
818+
// 2^20 * 24 bytes ~ 25 MB, which is acceptable IMHO.
819+
type_: InternedSet::with_capacity(1048576),
820+
// Const lists don't seem to be too common, but I still reserver 128 of them, since
821+
// it is cheap anyway
822+
const_lists: InternedSet::with_capacity(128),
823+
// From some experiments, it looks like there usualy are < 2^20 arg lists.
824+
// 2^20 * 8 bytes ~ 9 MB, which is acceptable IMHO.
825+
args: InternedSet::with_capacity(1048576),
826+
// From some experiments, it looks like there usualy are < 2^19 type_lists.
827+
type_lists: InternedSet::with_capacity(524288),
828+
region: InternedSet::with_capacity(4096),
829+
// There are usually very few `poly_existential_predicates` - for cargo, there were 119.
830+
// So, 256 ought to be more than enough for all cases.
831+
poly_existential_predicates: InternedSet::with_capacity(256),
832+
// There is usually very few `canonical_var_infos` - for cargo, there were 379.
833+
// So, 512 ought to be more than enough for all cases.
834+
canonical_var_infos: InternedSet::with_capacity(512),
835+
predicate: InternedSet::with_capacity(1024),
836+
clauses: InternedSet::with_capacity(1024),
837+
// Projs don't seem to be too common, but I still reserver 128 of them, since
838+
// it is cheap anyway
839+
projs: InternedSet::with_capacity(128),
840+
// There semes to be > 2^16 place_elems.
841+
place_elems: InternedSet::with_capacity(65536),
842+
const_: InternedSet::with_capacity(4096),
843+
pat: InternedSet::with_capacity(1024),
844+
const_allocation: InternedSet::with_capacity(1024),
845+
// There is usually < 2^13 bound_variable_kinds
846+
bound_variable_kinds: InternedSet::with_capacity(8192),
847+
layout: InternedSet::with_capacity(4096),
848+
adt_def: InternedSet::with_capacity(1024),
849+
external_constraints: InternedSet::with_capacity(1024),
850+
predefined_opaques_in_body: InternedSet::with_capacity(1024),
851+
fields: InternedSet::with_capacity(4096),
852+
local_def_ids: InternedSet::with_capacity(1024),
853+
captures: InternedSet::with_capacity(1024),
854+
offset_of: InternedSet::with_capacity(1024),
855+
valtree: InternedSet::with_capacity(1024),
841856
}
842857
}
843858

@@ -2549,6 +2564,7 @@ macro_rules! slice_interners {
25492564
($($field:ident: $vis:vis $method:ident($ty:ty)),+ $(,)?) => (
25502565
impl<'tcx> TyCtxt<'tcx> {
25512566
$($vis fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
2567+
//eprintln!("{} len:{}",stringify!($field), self.interners.$field.len());
25522568
if v.is_empty() {
25532569
List::empty()
25542570
} else {
@@ -2847,6 +2863,7 @@ impl<'tcx> TyCtxt<'tcx> {
28472863
// FIXME consider asking the input slice to be sorted to avoid
28482864
// re-interning permutations, in which case that would be asserted
28492865
// here.
2866+
28502867
self.intern_local_def_ids(clauses)
28512868
}
28522869

0 commit comments

Comments
 (0)