Skip to content

Commit b7830cf

Browse files
author
Markus Westerlind
committed
fix: Only instantiate RawTable's reserve functions once
...per key-value. Each of the previous closures would cause an entirely new reserve/resize function to be instantiated. By using this trick (which std uses for iterator adaptors), we always get a single instantiatiation per key (modulo the insert_with_hasher method).
1 parent 34c1189 commit b7830cf

File tree

1 file changed

+25
-18
lines changed

1 file changed

+25
-18
lines changed

src/map.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,13 @@ impl<K: Clone, V: Clone, S: Clone> Clone for HashMap<K, V, S> {
206206
}
207207
}
208208

209+
#[cfg_attr(feature = "inline-more", inline)]
210+
pub(crate) fn make_hasher<K: Hash, V>(
211+
hash_builder: &impl BuildHasher,
212+
) -> impl Fn(&(K, V)) -> u64 + '_ {
213+
move |val| make_hash(hash_builder, &val.0)
214+
}
215+
209216
#[cfg_attr(feature = "inline-more", inline)]
210217
pub(crate) fn make_hash<K: Hash + ?Sized>(hash_builder: &impl BuildHasher, val: &K) -> u64 {
211218
let mut state = hash_builder.build_hasher();
@@ -664,8 +671,7 @@ where
664671
#[cfg_attr(feature = "inline-more", inline)]
665672
pub fn reserve(&mut self, additional: usize) {
666673
let hash_builder = &self.hash_builder;
667-
self.table
668-
.reserve(additional, |x| make_hash(hash_builder, &x.0));
674+
self.table.reserve(additional, make_hasher(hash_builder));
669675
}
670676

671677
/// Tries to reserve capacity for at least `additional` more elements to be inserted
@@ -688,7 +694,7 @@ where
688694
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
689695
let hash_builder = &self.hash_builder;
690696
self.table
691-
.try_reserve(additional, |x| make_hash(hash_builder, &x.0))
697+
.try_reserve(additional, make_hasher(hash_builder))
692698
}
693699

694700
/// Shrinks the capacity of the map as much as possible. It will drop
@@ -710,7 +716,7 @@ where
710716
#[cfg_attr(feature = "inline-more", inline)]
711717
pub fn shrink_to_fit(&mut self) {
712718
let hash_builder = &self.hash_builder;
713-
self.table.shrink_to(0, |x| make_hash(hash_builder, &x.0));
719+
self.table.shrink_to(0, make_hasher(hash_builder));
714720
}
715721

716722
/// Shrinks the capacity of the map with a lower limit. It will drop
@@ -740,7 +746,7 @@ where
740746
pub fn shrink_to(&mut self, min_capacity: usize) {
741747
let hash_builder = &self.hash_builder;
742748
self.table
743-
.shrink_to(min_capacity, |x| make_hash(hash_builder, &x.0));
749+
.shrink_to(min_capacity, make_hasher(hash_builder));
744750
}
745751

746752
/// Gets the given key's corresponding entry in the map for in-place manipulation.
@@ -995,8 +1001,7 @@ where
9951001
Some(mem::replace(item, v))
9961002
} else {
9971003
let hash_builder = &self.hash_builder;
998-
self.table
999-
.insert(hash, (k, v), |x| make_hash(hash_builder, &x.0));
1004+
self.table.insert(hash, (k, v), make_hasher(hash_builder));
10001005
None
10011006
}
10021007
}
@@ -1946,7 +1951,10 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
19461951
S: BuildHasher,
19471952
{
19481953
let hash_builder = self.hash_builder;
1949-
self.insert_with_hasher(hash, key, value, |k| make_hash(hash_builder, k))
1954+
let &mut (ref mut k, ref mut v) =
1955+
self.table
1956+
.insert_entry(hash, (key, value), make_hasher(hash_builder));
1957+
(k, v)
19501958
}
19511959

19521960
/// Set the value of an entry with a custom hasher function.
@@ -1977,9 +1985,9 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
19771985
let mut hasher = self.hash_builder.build_hasher();
19781986
key.hash(&mut hasher);
19791987

1980-
let elem = self.table.insert(hasher.finish(), (key, value), |k| {
1981-
make_hash(hash_builder, &k.0)
1982-
});
1988+
let elem = self
1989+
.table
1990+
.insert(hasher.finish(), (key, value), make_hasher(hash_builder));
19831991
RawOccupiedEntryMut {
19841992
elem,
19851993
table: self.table,
@@ -2974,9 +2982,7 @@ impl<'a, K, V, S> VacantEntry<'a, K, V, S> {
29742982
{
29752983
let hash_builder = &self.table.hash_builder;
29762984
let table = &mut self.table.table;
2977-
let entry = table.insert_entry(self.hash, (self.key, value), |x| {
2978-
make_hash(hash_builder, &x.0)
2979-
});
2985+
let entry = table.insert_entry(self.hash, (self.key, value), make_hasher(hash_builder));
29802986
&mut entry.1
29812987
}
29822988

@@ -2987,9 +2993,10 @@ impl<'a, K, V, S> VacantEntry<'a, K, V, S> {
29872993
S: BuildHasher,
29882994
{
29892995
let hash_builder = &self.table.hash_builder;
2990-
let elem = self.table.table.insert(self.hash, (self.key, value), |x| {
2991-
make_hash(hash_builder, &x.0)
2992-
});
2996+
let elem = self
2997+
.table
2998+
.table
2999+
.insert(self.hash, (self.key, value), make_hasher(hash_builder));
29933000
OccupiedEntry {
29943001
hash: self.hash,
29953002
key: None,
@@ -4470,7 +4477,7 @@ mod test_map {
44704477
assert!(removed.contains(&(i, 2 * i)), "{} not in {:?}", i, removed);
44714478
let e = m
44724479
.table
4473-
.insert(hash, (i, 2 * i), |x| super::make_hash(&hasher, &x.0));
4480+
.insert(hash, (i, 2 * i), super::make_hasher(&hasher));
44744481
it.reflect_insert(&e);
44754482
if let Some(p) = removed.iter().position(|e| e == &(i, 2 * i)) {
44764483
removed.swap_remove(p);

0 commit comments

Comments
 (0)