Skip to content

Commit 92a0668

Browse files
committed
SsoHashMap minor refactoring, SSO_ARRAY_SIZE introduced
1 parent 41942fa commit 92a0668

File tree

1 file changed

+29
-12
lines changed
  • compiler/rustc_data_structures/src/sso

1 file changed

+29
-12
lines changed

compiler/rustc_data_structures/src/sso/map.rs

+29-12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@ use std::hash::Hash;
77
use std::iter::FromIterator;
88
use std::ops::Index;
99

10+
// For pointer-sized arguments arrays
11+
// are faster than set/map for up to 64
12+
// arguments.
13+
//
14+
// On the other hand such a big array
15+
// hurts cache performance, makes passing
16+
// sso structures around very expensive.
17+
//
18+
// Biggest performance benefit is gained
19+
// for reasonably small arrays that stay
20+
// small in vast majority of cases.
21+
//
22+
// '8' is choosen as a sane default, to be
23+
// reevaluated later.
24+
//
25+
// Note: As of now ArrayVec design prevents
26+
// us from making it user-customizable.
27+
const SSO_ARRAY_SIZE: usize = 8;
28+
1029
/// Small-storage-optimized implementation of a map.
1130
///
1231
/// Stores elements in a small array up to a certain length
@@ -26,7 +45,7 @@ use std::ops::Index;
2645
/// Vacant/Occupied entries and related
2746
#[derive(Clone)]
2847
pub enum SsoHashMap<K, V> {
29-
Array(ArrayVec<[(K, V); 8]>),
48+
Array(ArrayVec<[(K, V); SSO_ARRAY_SIZE]>),
3049
Map(FxHashMap<K, V>),
3150
}
3251

@@ -39,9 +58,8 @@ impl<K, V> SsoHashMap<K, V> {
3958

4059
/// Creates an empty `SsoHashMap` with the specified capacity.
4160
pub fn with_capacity(cap: usize) -> Self {
42-
let array = ArrayVec::new();
43-
if array.capacity() >= cap {
44-
SsoHashMap::Array(array)
61+
if cap <= SSO_ARRAY_SIZE {
62+
Self::new()
4563
} else {
4664
SsoHashMap::Map(FxHashMap::with_capacity_and_hasher(cap, Default::default()))
4765
}
@@ -59,7 +77,7 @@ impl<K, V> SsoHashMap<K, V> {
5977
/// Returns the number of elements the map can hold without reallocating.
6078
pub fn capacity(&self) -> usize {
6179
match self {
62-
SsoHashMap::Array(array) => array.capacity(),
80+
SsoHashMap::Array(_) => SSO_ARRAY_SIZE,
6381
SsoHashMap::Map(map) => map.capacity(),
6482
}
6583
}
@@ -149,7 +167,7 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
149167
pub fn reserve(&mut self, additional: usize) {
150168
match self {
151169
SsoHashMap::Array(array) => {
152-
if array.capacity() < (array.len() + additional) {
170+
if SSO_ARRAY_SIZE < (array.len() + additional) {
153171
let mut map: FxHashMap<K, V> = array.drain(..).collect();
154172
map.reserve(additional);
155173
*self = SsoHashMap::Map(map);
@@ -164,10 +182,8 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
164182
/// and possibly leaving some space in accordance with the resize policy.
165183
pub fn shrink_to_fit(&mut self) {
166184
if let SsoHashMap::Map(map) = self {
167-
let mut array = ArrayVec::new();
168-
if map.len() <= array.capacity() {
169-
array.extend(map.drain());
170-
*self = SsoHashMap::Array(array);
185+
if map.len() <= SSO_ARRAY_SIZE {
186+
*self = SsoHashMap::Array(map.drain().collect());
171187
} else {
172188
map.shrink_to_fit();
173189
}
@@ -361,7 +377,7 @@ impl<K: Eq + Hash, V> Extend<(K, V)> for SsoHashMap<K, V> {
361377
fn extend_reserve(&mut self, additional: usize) {
362378
match self {
363379
SsoHashMap::Array(array) => {
364-
if array.capacity() < (array.len() + additional) {
380+
if SSO_ARRAY_SIZE < (array.len() + additional) {
365381
let mut map: FxHashMap<K, V> = array.drain(..).collect();
366382
map.extend_reserve(additional);
367383
*self = SsoHashMap::Map(map);
@@ -517,8 +533,9 @@ impl<'a, K: Eq + Hash, V> Entry<'a, K, V> {
517533
let index = if let Some(index) = found_index {
518534
index
519535
} else {
536+
let index = array.len();
520537
array.try_push((self.key, default())).unwrap();
521-
array.len() - 1
538+
index
522539
};
523540
&mut array[index].1
524541
}

0 commit comments

Comments
 (0)