Skip to content

Commit 3c3aca6

Browse files
committed
doc
1 parent 70450dd commit 3c3aca6

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

src/adaptive_hashing.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,10 @@ impl Hasher for AdaptiveHasher {
9898
#[inline]
9999
fn write(&mut self, msg: &[u8]) {
100100
if let Some(ref mut hasher) = self.safe_hasher {
101+
// Use safe hashing.
101102
hasher.write(msg);
102103
} else {
104+
// Use fast hashing.
103105
let msg_data = unsafe {
104106
if msg.len() <= 8 {
105107
load_u64_le(msg, msg.len())
@@ -114,8 +116,10 @@ impl Hasher for AdaptiveHasher {
114116
#[inline]
115117
fn finish(&self) -> u64 {
116118
if let Some(ref hasher) = self.safe_hasher {
119+
// Use safe hashing.
117120
hasher.finish()
118121
} else {
122+
// Use fast hashing.
119123
self.hash
120124
}
121125
}

src/adaptive_map.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ const LOAD_FACTOR_THRESHOLD: f32 = 0.625;
3333
// The displacement threshold should be high enough so that even with the maximal load factor,
3434
// it's very rarely exceeded.
3535
// As the load approaches 90%, displacements larger than ~ 32 are much more probable.
36+
// On the other hand, the threshold should be low enough so that the same number of hashes
37+
// easily fits in the cache and takes a reasonable time to iterate through.
38+
39+
// The load factor threshold should be relatively low, but high enough so that its half is not very
40+
// low (~ 20%). We choose 62.5%, because it's a simple fraction (5/8), and its half is 31.25%.
41+
// (When a map is grown, the load factor is halved.)
42+
43+
// TODO: add one-shot hashing for String, str, arrays and other types.
44+
// TODO: consider adding a limit for the number of fully equal hashes in a probe sequence.
45+
// Fully equal hashes cause key comparison, which might be a problem for large string keys.
3646

3747
// Avoid problems with private types in public interfaces.
3848
pub type InternalEntryMut<'a, K: 'a, V: 'a> = InternalEntry<K, V, &'a mut RawTable<K, V>>;
@@ -65,7 +75,7 @@ impl<K, V> SafeguardedSearch<K, V> for HashMap<K, V, AdaptiveState>
6575
let entry = search_hashed(DerefMapToTable(self), hash, |k| k == key);
6676
match entry {
6777
InternalEntry::Occupied { elem } => {
68-
// This should compile down to a no-op.
78+
// This should compile down to a simple copy.
6979
InternalEntry::Occupied { elem: elem.convert_table() }
7080
}
7181
InternalEntry::TableIsEmpty => {
@@ -102,12 +112,13 @@ fn safeguard_vacant_entry<'a, K, V>(
102112
};
103113
// Copied from FullBucket::displacement.
104114
let displacement = index.wrapping_sub(hash.inspect() as usize) & (table_capacity - 1);
115+
// Check displacement.
105116
if displacement > DISPLACEMENT_THRESHOLD {
106117
// Probe sequence is too long.
107118
// This branch is very unlikely.
108119
maybe_adapt_to_safe_hashing(elem, key, hash)
109120
} else {
110-
// This should compile down to a no-op.
121+
// This should compile down to a simple copy.
111122
match elem {
112123
NeqElem(bucket, ib) => {
113124
InternalEntry::Vacant {
@@ -125,7 +136,7 @@ fn safeguard_vacant_entry<'a, K, V>(
125136
}
126137
}
127138

128-
// Adapt to safe hashing if desirable.
139+
// Adapt to safe hashing, if desirable.
129140
#[cold]
130141
fn maybe_adapt_to_safe_hashing<'a, K, V>(
131142
elem: VacantEntryState<K, V, DerefMapToTable<'a, K, V, AdaptiveState>>,

0 commit comments

Comments
 (0)