Skip to content

Commit 3d315aa

Browse files
authoredApr 27, 2022
Hash keys once (#194)
1 parent 0516c3c commit 3d315aa

File tree

4 files changed

+91
-66
lines changed

4 files changed

+91
-66
lines changed
 

‎Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ send_guard = ["parking_lot/send_guard"]
2020
[dependencies]
2121
num_cpus = "1.13.1"
2222
parking_lot = "0.12.0"
23+
hashbrown = "0.11.2"
2324
serde = { version = "1.0.136", optional = true, features = ["derive"] }
2425
cfg-if = "1.0.0"
2526
rayon = { version = "1.5.1", optional = true }

‎src/iter.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::{DashMap, HashMap};
66
use core::hash::{BuildHasher, Hash};
77
use core::mem;
88
use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
9-
use std::collections::hash_map;
109
use std::collections::hash_map::RandomState;
1110
use std::sync::Arc;
1211

@@ -39,7 +38,7 @@ impl<K: Eq + Hash, V, S: BuildHasher + Clone> OwningIter<K, V, S> {
3938
}
4039
}
4140

42-
type GuardOwningIter<K, V> = hash_map::IntoIter<K, SharedValue<V>>;
41+
type GuardOwningIter<K, V> = hashbrown::hash_map::IntoIter<K, SharedValue<V>>;
4342

4443
impl<K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for OwningIter<K, V, S> {
4544
type Item = (K, V);
@@ -93,12 +92,12 @@ where
9392

9493
type GuardIter<'a, K, V, S> = (
9594
Arc<RwLockReadGuard<'a, HashMap<K, V, S>>>,
96-
hash_map::Iter<'a, K, SharedValue<V>>,
95+
hashbrown::hash_map::Iter<'a, K, SharedValue<V>>,
9796
);
9897

9998
type GuardIterMut<'a, K, V, S> = (
10099
Arc<RwLockWriteGuard<'a, HashMap<K, V, S>>>,
101-
hash_map::IterMut<'a, K, SharedValue<V>>,
100+
hashbrown::hash_map::IterMut<'a, K, SharedValue<V>>,
102101
);
103102

104103
/// Iterator over a DashMap yielding immutable references.

‎src/lib.rs

+69-53
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ cfg_if! {
4343
}
4444
}
4545

46-
pub(crate) type HashMap<K, V, S> = std::collections::HashMap<K, SharedValue<V>, S>;
46+
pub(crate) type HashMap<K, V, S> = hashbrown::HashMap<K, SharedValue<V>, S>;
4747

4848
fn default_shard_amount() -> usize {
4949
(num_cpus::get() * 4).next_power_of_two()
@@ -271,14 +271,18 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
271271
}
272272
}
273273

274-
/// Hash a given item to produce a usize.
275-
/// Uses the provided or default HashBuilder.
276-
pub fn hash_usize<T: Hash>(&self, item: &T) -> usize {
274+
fn hash_u64<T: Hash>(&self, item: &T) -> u64 {
277275
let mut hasher = self.hasher.build_hasher();
278276

279277
item.hash(&mut hasher);
280278

281-
hasher.finish() as usize
279+
hasher.finish()
280+
}
281+
282+
/// Hash a given item to produce a usize.
283+
/// Uses the provided or default HashBuilder.
284+
pub fn hash_usize<T: Hash>(&self, item: &T) -> usize {
285+
self.hash_u64(item) as usize
282286
}
283287

284288
cfg_if! {
@@ -329,8 +333,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
329333
K: Borrow<Q>,
330334
Q: Hash + Eq + ?Sized,
331335
{
332-
let hash = self.hash_usize(&key);
333-
self.determine_shard(hash)
336+
let hash = self.hash_u64(&key);
337+
self.determine_shard(hash as usize)
334338
}
335339
}
336340
}
@@ -837,50 +841,64 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
837841
}
838842

839843
fn _insert(&self, key: K, value: V) -> Option<V> {
840-
let hash = self.hash_usize(&key);
844+
let hash = self.hash_u64(&key);
841845

842-
let idx = self.determine_shard(hash);
846+
let idx = self.determine_shard(hash as usize);
843847

844848
let mut shard = unsafe { self._yield_write_shard(idx) };
845849

846-
shard
847-
.insert(key, SharedValue::new(value))
848-
.map(|v| v.into_inner())
850+
match shard.raw_entry_mut().from_key_hashed_nocheck(hash, &key) {
851+
hashbrown::hash_map::RawEntryMut::Occupied(mut occupied) => {
852+
Some(occupied.insert(SharedValue::new(value)).into_inner())
853+
}
854+
hashbrown::hash_map::RawEntryMut::Vacant(vacant) => {
855+
vacant.insert(key, SharedValue::new(value));
856+
None
857+
}
858+
}
849859
}
850860

851861
fn _remove<Q>(&self, key: &Q) -> Option<(K, V)>
852862
where
853863
K: Borrow<Q>,
854864
Q: Hash + Eq + ?Sized,
855865
{
856-
let hash = self.hash_usize(&key);
866+
let hash = self.hash_u64(&key);
857867

858-
let idx = self.determine_shard(hash);
868+
let idx = self.determine_shard(hash as usize);
859869

860870
let mut shard = unsafe { self._yield_write_shard(idx) };
861871

862-
shard.remove_entry(key).map(|(k, v)| (k, v.into_inner()))
872+
match shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) {
873+
hashbrown::hash_map::RawEntryMut::Occupied(entry) => {
874+
let (k, v) = entry.remove_entry();
875+
Some((k, v.into_inner()))
876+
}
877+
hashbrown::hash_map::RawEntryMut::Vacant(_) => None,
878+
}
863879
}
864880

865881
fn _remove_if<Q>(&self, key: &Q, f: impl FnOnce(&K, &V) -> bool) -> Option<(K, V)>
866882
where
867883
K: Borrow<Q>,
868884
Q: Hash + Eq + ?Sized,
869885
{
870-
let hash = self.hash_usize(&key);
886+
let hash = self.hash_u64(&key);
871887

872-
let idx = self.determine_shard(hash);
888+
let idx = self.determine_shard(hash as usize);
873889

874890
let mut shard = unsafe { self._yield_write_shard(idx) };
875891

876-
if let Some((k, v)) = shard.get_key_value(key) {
877-
if f(k, v.get()) {
878-
shard.remove_entry(key).map(|(k, v)| (k, v.into_inner()))
879-
} else {
880-
None
892+
match shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) {
893+
hashbrown::hash_map::RawEntryMut::Occupied(occupied) => {
894+
if f(&occupied.key(), &occupied.get().get()) {
895+
let (k, v) = occupied.remove_entry();
896+
Some((k, v.into_inner()))
897+
} else {
898+
None
899+
}
881900
}
882-
} else {
883-
None
901+
hashbrown::hash_map::RawEntryMut::Vacant(_) => None,
884902
}
885903
}
886904

@@ -889,25 +907,23 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
889907
K: Borrow<Q>,
890908
Q: Hash + Eq + ?Sized,
891909
{
892-
let hash = self.hash_usize(&key);
910+
let hash = self.hash_u64(&key);
893911

894-
let idx = self.determine_shard(hash);
912+
let idx = self.determine_shard(hash as usize);
895913

896914
let mut shard = unsafe { self._yield_write_shard(idx) };
897915

898-
if let Some((kptr, vptr)) = shard.get_key_value(&key) {
899-
unsafe {
900-
let kptr: *const K = kptr;
901-
let vptr: *mut V = vptr.as_ptr();
902-
903-
if f(&*kptr, &mut *vptr) {
904-
shard.remove_entry(key).map(|(k, v)| (k, v.into_inner()))
916+
match shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) {
917+
hashbrown::hash_map::RawEntryMut::Occupied(mut occupied) => {
918+
let (k, v) = occupied.get_key_value_mut();
919+
if f(k, v.get_mut()) {
920+
let (k, v) = occupied.remove_entry();
921+
Some((k, v.into_inner()))
905922
} else {
906923
None
907924
}
908925
}
909-
} else {
910-
None
926+
hashbrown::hash_map::RawEntryMut::Vacant(_) => None,
911927
}
912928
}
913929

@@ -924,13 +940,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
924940
K: Borrow<Q>,
925941
Q: Hash + Eq + ?Sized,
926942
{
927-
let hash = self.hash_usize(&key);
943+
let hash = self.hash_u64(&key);
928944

929-
let idx = self.determine_shard(hash);
945+
let idx = self.determine_shard(hash as usize);
930946

931947
let shard = unsafe { self._yield_read_shard(idx) };
932948

933-
if let Some((kptr, vptr)) = shard.get_key_value(key) {
949+
if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) {
934950
unsafe {
935951
let kptr: *const K = kptr;
936952
let vptr: *const V = vptr.get();
@@ -946,13 +962,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
946962
K: Borrow<Q>,
947963
Q: Hash + Eq + ?Sized,
948964
{
949-
let hash = self.hash_usize(&key);
965+
let hash = self.hash_u64(&key);
950966

951-
let idx = self.determine_shard(hash);
967+
let idx = self.determine_shard(hash as usize);
952968

953969
let shard = unsafe { self._yield_write_shard(idx) };
954970

955-
if let Some((kptr, vptr)) = shard.get_key_value(key) {
971+
if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) {
956972
unsafe {
957973
let kptr: *const K = kptr;
958974
let vptr: *mut V = vptr.as_ptr();
@@ -968,16 +984,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
968984
K: Borrow<Q>,
969985
Q: Hash + Eq + ?Sized,
970986
{
971-
let hash = self.hash_usize(&key);
987+
let hash = self.hash_u64(&key);
972988

973-
let idx = self.determine_shard(hash);
989+
let idx = self.determine_shard(hash as usize);
974990

975991
let shard = match unsafe { self._try_yield_read_shard(idx) } {
976992
Some(shard) => shard,
977993
None => return TryResult::Locked,
978994
};
979995

980-
if let Some((kptr, vptr)) = shard.get_key_value(key) {
996+
if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) {
981997
unsafe {
982998
let kptr: *const K = kptr;
983999
let vptr: *const V = vptr.get();
@@ -993,16 +1009,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
9931009
K: Borrow<Q>,
9941010
Q: Hash + Eq + ?Sized,
9951011
{
996-
let hash = self.hash_usize(&key);
1012+
let hash = self.hash_u64(&key);
9971013

998-
let idx = self.determine_shard(hash);
1014+
let idx = self.determine_shard(hash as usize);
9991015

10001016
let shard = match unsafe { self._try_yield_write_shard(idx) } {
10011017
Some(shard) => shard,
10021018
None => return TryResult::Locked,
10031019
};
10041020

1005-
if let Some((kptr, vptr)) = shard.get_key_value(key) {
1021+
if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) {
10061022
unsafe {
10071023
let kptr: *const K = kptr;
10081024
let vptr: *mut V = vptr.as_ptr();
@@ -1061,13 +1077,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10611077
}
10621078

10631079
fn _entry(&'a self, key: K) -> Entry<'a, K, V, S> {
1064-
let hash = self.hash_usize(&key);
1080+
let hash = self.hash_u64(&key);
10651081

1066-
let idx = self.determine_shard(hash);
1082+
let idx = self.determine_shard(hash as usize);
10671083

10681084
let shard = unsafe { self._yield_write_shard(idx) };
10691085

1070-
if let Some((kptr, vptr)) = shard.get_key_value(&key) {
1086+
if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, &key) {
10711087
unsafe {
10721088
let kptr: *const K = kptr;
10731089
let vptr: *mut V = vptr.as_ptr();
@@ -1079,16 +1095,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10791095
}
10801096

10811097
fn _try_entry(&'a self, key: K) -> Option<Entry<'a, K, V, S>> {
1082-
let hash = self.hash_usize(&key);
1098+
let hash = self.hash_u64(&key);
10831099

1084-
let idx = self.determine_shard(hash);
1100+
let idx = self.determine_shard(hash as usize);
10851101

10861102
let shard = match unsafe { self._try_yield_write_shard(idx) } {
10871103
Some(shard) => shard,
10881104
None => return None,
10891105
};
10901106

1091-
if let Some((kptr, vptr)) = shard.get_key_value(&key) {
1107+
if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, &key) {
10921108
unsafe {
10931109
let kptr: *const K = kptr;
10941110
let vptr: *mut V = vptr.as_ptr();

‎src/read_only.rs

+18-9
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S>
5959
K: Borrow<Q>,
6060
Q: Hash + Eq + ?Sized,
6161
{
62-
let hash = self.map.hash_usize(&key);
62+
let hash = self.map.hash_u64(&key);
6363

64-
let idx = self.map.determine_shard(hash);
64+
let idx = self.map.determine_shard(hash as usize);
6565

6666
let shard = unsafe { self.map._get_read_shard(idx) };
6767

68-
shard.contains_key(key)
68+
shard
69+
.raw_entry()
70+
.from_key_hashed_nocheck(hash, key)
71+
.is_some()
6972
}
7073

7174
/// Returns a reference to the value corresponding to the key.
@@ -74,13 +77,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S>
7477
K: Borrow<Q>,
7578
Q: Hash + Eq + ?Sized,
7679
{
77-
let hash = self.map.hash_usize(&key);
80+
let hash = self.map.hash_u64(&key);
7881

79-
let idx = self.map.determine_shard(hash);
82+
let idx = self.map.determine_shard(hash as usize);
8083

8184
let shard = unsafe { self.map._get_read_shard(idx) };
8285

83-
shard.get(key).map(|v| v.get())
86+
shard
87+
.raw_entry()
88+
.from_key_hashed_nocheck(hash, key)
89+
.map(|(_k, v)| v.get())
8490
}
8591

8692
/// Returns the key-value pair corresponding to the supplied key.
@@ -89,13 +95,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S>
8995
K: Borrow<Q>,
9096
Q: Hash + Eq + ?Sized,
9197
{
92-
let hash = self.map.hash_usize(&key);
98+
let hash = self.map.hash_u64(&key);
9399

94-
let idx = self.map.determine_shard(hash);
100+
let idx = self.map.determine_shard(hash as usize);
95101

96102
let shard = unsafe { self.map._get_read_shard(idx) };
97103

98-
shard.get_key_value(key).map(|(k, v)| (k, v.get()))
104+
shard
105+
.raw_entry()
106+
.from_key_hashed_nocheck(hash, key)
107+
.map(|(k, v)| (k, v.get()))
99108
}
100109

101110
fn shard_read_iter(&'a self) -> impl Iterator<Item = &'a HashMap<K, V, S>> + 'a {

0 commit comments

Comments
 (0)
Please sign in to comment.