From 3448b6f070e1b4b2d78fbd1e07999a73295081f9 Mon Sep 17 00:00:00 2001 From: Arthur Silva Date: Tue, 22 Aug 2023 01:57:35 +0200 Subject: [PATCH 1/9] Only hash keys once, taking advantage of hashbrown raw entry api (#259) --- src/lib.rs | 104 ++++++++++++++++++++++++----------------------- src/read_only.rs | 25 ++++-------- 2 files changed, 62 insertions(+), 67 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 34e5d8ba..a74e1363 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ use core::fmt; use core::hash::{BuildHasher, Hash, Hasher}; use core::iter::FromIterator; use core::ops::{BitAnd, BitOr, Shl, Shr, Sub}; +use hashbrown::hash_map::RawEntryMut; use iter::{Iter, IterMut, OwningIter}; use mapref::entry::{Entry, OccupiedEntry, VacantEntry}; use mapref::multiple::RefMulti; @@ -295,11 +296,15 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// Hash a given item to produce a usize. /// Uses the provided or default HashBuilder. pub fn hash_usize(&self, item: &T) -> usize { + self.hash_u64(item) as usize + } + + fn hash_u64(&self, item: &T) -> u64 { let mut hasher = self.hasher.build_hasher(); item.hash(&mut hasher); - hasher.finish() as usize + hasher.finish() } cfg_if! { @@ -916,9 +921,9 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> } fn _insert(&self, key: K, value: V) -> Option { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let mut shard = unsafe { self._yield_write_shard(idx) }; @@ -932,9 +937,9 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let mut shard = unsafe { self._yield_write_shard(idx) }; @@ -946,22 +951,20 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let mut shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { - unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); - - if f(&*kptr, &mut *vptr) { - shard.remove_entry(key).map(|(k, v)| (k, v.into_inner())) - } else { - None - } + if let RawEntryMut::Occupied(entry) = + shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) + { + if f(&entry.key(), &entry.get().get()) { + let (k, v) = entry.remove_entry(); + Some((k, v.into_inner())) + } else { + None } } else { None @@ -973,22 +976,21 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let mut shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { - unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); - - if f(&*kptr, &mut *vptr) { - shard.remove_entry(key).map(|(k, v)| (k, v.into_inner())) - } else { - None - } + if let RawEntryMut::Occupied(mut entry) = + shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) + { + let (k, v) = entry.get_key_value_mut(); + if f(k, v.get_mut()) { + let (k, v) = entry.remove_entry(); + Some((k, v.into_inner())) + } else { + None } } else { None @@ -1008,13 +1010,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = unsafe { self._yield_read_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { + if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) { unsafe { let kptr: *const K = kptr; let vptr: *const V = vptr.get(); @@ -1030,16 +1032,18 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); - let shard = unsafe { self._yield_write_shard(idx) }; + let mut shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { + if let RawEntryMut::Occupied(mut entry) = + shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) + { unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); + let kptr: *const K = entry.key(); + let vptr: *mut V = entry.get_mut().as_ptr(); Some(RefMut::new(shard, kptr, vptr)) } } else { @@ -1052,16 +1056,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = match unsafe { self._try_yield_read_shard(idx) } { Some(shard) => shard, None => return TryResult::Locked, }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { + if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) { unsafe { let kptr: *const K = kptr; let vptr: *const V = vptr.get(); @@ -1077,16 +1081,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = match unsafe { self._try_yield_write_shard(idx) } { Some(shard) => shard, None => return TryResult::Locked, }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { + if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) { unsafe { let kptr: *const K = kptr; let vptr: *mut V = vptr.as_ptr(); @@ -1145,13 +1149,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> } fn _entry(&'a self, key: K) -> Entry<'a, K, V, S> { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(&key) { + if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, &key) { unsafe { let kptr: *const K = kptr; let vptr: *mut V = vptr.as_ptr(); @@ -1163,16 +1167,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> } fn _try_entry(&'a self, key: K) -> Option> { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = match unsafe { self._try_yield_write_shard(idx) } { Some(shard) => shard, None => return None, }; - if let Some((kptr, vptr)) = shard.get_key_value(&key) { + if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, &key) { unsafe { let kptr: *const K = kptr; let vptr: *mut V = vptr.as_ptr(); diff --git a/src/read_only.rs b/src/read_only.rs index 42ee4433..a8feb43e 100644 --- a/src/read_only.rs +++ b/src/read_only.rs @@ -61,13 +61,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.map.hash_usize(&key); - - let idx = self.map.determine_shard(hash); - - let shard = unsafe { self.map._get_read_shard(idx) }; - - shard.contains_key(key) + self.get(key).is_some() } /// Returns a reference to the value corresponding to the key. @@ -76,13 +70,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.map.hash_usize(&key); - - let idx = self.map.determine_shard(hash); - - let shard = unsafe { self.map._get_read_shard(idx) }; - - shard.get(key).map(|v| v.get()) + self.get_key_value(key).map(|(_k, v)| v) } /// Returns the key-value pair corresponding to the supplied key. @@ -91,13 +79,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.map.hash_usize(&key); + let hash = self.map.hash_u64(&key); - let idx = self.map.determine_shard(hash); + let idx = self.map.determine_shard(hash as usize); let shard = unsafe { self.map._get_read_shard(idx) }; - shard.get_key_value(key).map(|(k, v)| (k, v.get())) + shard + .raw_entry() + .from_key_hashed_nocheck(hash, key) + .map(|(k, v)| (k, v.get())) } fn shard_read_iter(&'a self) -> impl Iterator> + 'a { From 8364d3e48ec230e27dc5dec48ebc2b9b611a687a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Tue, 22 Aug 2023 02:00:33 +0200 Subject: [PATCH 2/9] fix lint --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index a74e1363..800a8d5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -960,7 +960,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> if let RawEntryMut::Occupied(entry) = shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) { - if f(&entry.key(), &entry.get().get()) { + if f(entry.key(), entry.get().get()) { let (k, v) = entry.remove_entry(); Some((k, v.into_inner())) } else { From 71a1dc6cd892fdd824fee4f811e64b70798bd73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Tue, 22 Aug 2023 02:01:56 +0200 Subject: [PATCH 3/9] rename toolchain file --- rust-toolchain => rust-toolchain.toml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rust-toolchain => rust-toolchain.toml (100%) diff --git a/rust-toolchain b/rust-toolchain.toml similarity index 100% rename from rust-toolchain rename to rust-toolchain.toml From 3b26d70d2f9876ca7369935714c04e28d51c8696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Tue, 22 Aug 2023 02:05:50 +0200 Subject: [PATCH 4/9] commit lockfile --- .gitignore | 1 - Cargo.lock | 311 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index 69369904..53eaa219 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /target **/*.rs.bk -Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..6629e669 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,311 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arbitrary" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "dashmap" +version = "5.5.0" +dependencies = [ + "arbitrary", + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", + "rayon", + "serde", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "syn" +version = "2.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" From dfb7b9af33e157bff8ed3061c64659ed79a3f538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Tue, 22 Aug 2023 02:06:11 +0200 Subject: [PATCH 5/9] v5.5.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6629e669..c173aa42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.0" +version = "5.5.1" dependencies = [ "arbitrary", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index c1bb1102..ddef7eb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dashmap" -version = "5.5.0" +version = "5.5.1" authors = ["Acrimon "] edition = "2018" rust-version = "1.64" From febc45dc62eecf3415024bb819e1aec7e4a063a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Tue, 29 Aug 2023 13:17:03 +0200 Subject: [PATCH 6/9] Revert "Only hash keys once, taking advantage of hashbrown raw entry api (#259)" This reverts commit 3448b6f070e1b4b2d78fbd1e07999a73295081f9. --- src/lib.rs | 104 +++++++++++++++++++++++------------------------ src/read_only.rs | 25 ++++++++---- 2 files changed, 67 insertions(+), 62 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 800a8d5e..34e5d8ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,6 @@ use core::fmt; use core::hash::{BuildHasher, Hash, Hasher}; use core::iter::FromIterator; use core::ops::{BitAnd, BitOr, Shl, Shr, Sub}; -use hashbrown::hash_map::RawEntryMut; use iter::{Iter, IterMut, OwningIter}; use mapref::entry::{Entry, OccupiedEntry, VacantEntry}; use mapref::multiple::RefMulti; @@ -296,15 +295,11 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// Hash a given item to produce a usize. /// Uses the provided or default HashBuilder. pub fn hash_usize(&self, item: &T) -> usize { - self.hash_u64(item) as usize - } - - fn hash_u64(&self, item: &T) -> u64 { let mut hasher = self.hasher.build_hasher(); item.hash(&mut hasher); - hasher.finish() + hasher.finish() as usize } cfg_if! { @@ -921,9 +916,9 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> } fn _insert(&self, key: K, value: V) -> Option { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let mut shard = unsafe { self._yield_write_shard(idx) }; @@ -937,9 +932,9 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let mut shard = unsafe { self._yield_write_shard(idx) }; @@ -951,20 +946,22 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let mut shard = unsafe { self._yield_write_shard(idx) }; - if let RawEntryMut::Occupied(entry) = - shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) - { - if f(entry.key(), entry.get().get()) { - let (k, v) = entry.remove_entry(); - Some((k, v.into_inner())) - } else { - None + if let Some((kptr, vptr)) = shard.get_key_value(key) { + unsafe { + let kptr: *const K = kptr; + let vptr: *mut V = vptr.as_ptr(); + + if f(&*kptr, &mut *vptr) { + shard.remove_entry(key).map(|(k, v)| (k, v.into_inner())) + } else { + None + } } } else { None @@ -976,21 +973,22 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let mut shard = unsafe { self._yield_write_shard(idx) }; - if let RawEntryMut::Occupied(mut entry) = - shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) - { - let (k, v) = entry.get_key_value_mut(); - if f(k, v.get_mut()) { - let (k, v) = entry.remove_entry(); - Some((k, v.into_inner())) - } else { - None + if let Some((kptr, vptr)) = shard.get_key_value(key) { + unsafe { + let kptr: *const K = kptr; + let vptr: *mut V = vptr.as_ptr(); + + if f(&*kptr, &mut *vptr) { + shard.remove_entry(key).map(|(k, v)| (k, v.into_inner())) + } else { + None + } } } else { None @@ -1010,13 +1008,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let shard = unsafe { self._yield_read_shard(idx) }; - if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) { + if let Some((kptr, vptr)) = shard.get_key_value(key) { unsafe { let kptr: *const K = kptr; let vptr: *const V = vptr.get(); @@ -1032,18 +1030,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); - let mut shard = unsafe { self._yield_write_shard(idx) }; + let shard = unsafe { self._yield_write_shard(idx) }; - if let RawEntryMut::Occupied(mut entry) = - shard.raw_entry_mut().from_key_hashed_nocheck(hash, key) - { + if let Some((kptr, vptr)) = shard.get_key_value(key) { unsafe { - let kptr: *const K = entry.key(); - let vptr: *mut V = entry.get_mut().as_ptr(); + let kptr: *const K = kptr; + let vptr: *mut V = vptr.as_ptr(); Some(RefMut::new(shard, kptr, vptr)) } } else { @@ -1056,16 +1052,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let shard = match unsafe { self._try_yield_read_shard(idx) } { Some(shard) => shard, None => return TryResult::Locked, }; - if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) { + if let Some((kptr, vptr)) = shard.get_key_value(key) { unsafe { let kptr: *const K = kptr; let vptr: *const V = vptr.get(); @@ -1081,16 +1077,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let shard = match unsafe { self._try_yield_write_shard(idx) } { Some(shard) => shard, None => return TryResult::Locked, }; - if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, key) { + if let Some((kptr, vptr)) = shard.get_key_value(key) { unsafe { let kptr: *const K = kptr; let vptr: *mut V = vptr.as_ptr(); @@ -1149,13 +1145,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> } fn _entry(&'a self, key: K) -> Entry<'a, K, V, S> { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, &key) { + if let Some((kptr, vptr)) = shard.get_key_value(&key) { unsafe { let kptr: *const K = kptr; let vptr: *mut V = vptr.as_ptr(); @@ -1167,16 +1163,16 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> } fn _try_entry(&'a self, key: K) -> Option> { - let hash = self.hash_u64(&key); + let hash = self.hash_usize(&key); - let idx = self.determine_shard(hash as usize); + let idx = self.determine_shard(hash); let shard = match unsafe { self._try_yield_write_shard(idx) } { Some(shard) => shard, None => return None, }; - if let Some((kptr, vptr)) = shard.raw_entry().from_key_hashed_nocheck(hash, &key) { + if let Some((kptr, vptr)) = shard.get_key_value(&key) { unsafe { let kptr: *const K = kptr; let vptr: *mut V = vptr.as_ptr(); diff --git a/src/read_only.rs b/src/read_only.rs index a8feb43e..42ee4433 100644 --- a/src/read_only.rs +++ b/src/read_only.rs @@ -61,7 +61,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - self.get(key).is_some() + let hash = self.map.hash_usize(&key); + + let idx = self.map.determine_shard(hash); + + let shard = unsafe { self.map._get_read_shard(idx) }; + + shard.contains_key(key) } /// Returns a reference to the value corresponding to the key. @@ -70,7 +76,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - self.get_key_value(key).map(|(_k, v)| v) + let hash = self.map.hash_usize(&key); + + let idx = self.map.determine_shard(hash); + + let shard = unsafe { self.map._get_read_shard(idx) }; + + shard.get(key).map(|v| v.get()) } /// Returns the key-value pair corresponding to the supplied key. @@ -79,16 +91,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.map.hash_u64(&key); + let hash = self.map.hash_usize(&key); - let idx = self.map.determine_shard(hash as usize); + let idx = self.map.determine_shard(hash); let shard = unsafe { self.map._get_read_shard(idx) }; - shard - .raw_entry() - .from_key_hashed_nocheck(hash, key) - .map(|(k, v)| (k, v.get())) + shard.get_key_value(key).map(|(k, v)| (k, v.get())) } fn shard_read_iter(&'a self) -> impl Iterator> + 'a { From eff796d46b205c1c77b863ac69039fe5f0268ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Tue, 29 Aug 2023 13:17:51 +0200 Subject: [PATCH 7/9] v5.5.2 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c173aa42..632a454e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.1" +version = "5.5.2" dependencies = [ "arbitrary", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index ddef7eb9..8adaa88b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dashmap" -version = "5.5.1" +version = "5.5.2" authors = ["Acrimon "] edition = "2018" rust-version = "1.64" From 1e7efe58431343a5c662fd9aca2d290dcc2c1e56 Mon Sep 17 00:00:00 2001 From: Joel Date: Tue, 29 Aug 2023 23:12:11 +0200 Subject: [PATCH 8/9] bump msrv to 1.65 (#279) --- Cargo.lock | 8 ++++---- Cargo.toml | 4 ++-- README.md | 2 +- rust-toolchain.toml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 632a454e..bb38a546 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,18 +212,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 8adaa88b..4d77d168 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "dashmap" version = "5.5.2" authors = ["Acrimon "] edition = "2018" -rust-version = "1.64" +rust-version = "1.65" license = "MIT" repository = "https://github.com/xacrimon/dashmap" homepage = "https://github.com/xacrimon/dashmap" @@ -21,7 +21,7 @@ inline = ["hashbrown/inline-more"] lock_api = "0.4.10" parking_lot_core = "0.9.8" hashbrown = { version = "0.14.0", default-features = false } -serde = { version = "1.0.171", optional = true, features = ["derive"] } +serde = { version = "1.0.188", optional = true, features = ["derive"] } cfg-if = "1.0.0" rayon = { version = "1.7.0", optional = true } once_cell = "1.18.0" diff --git a/README.md b/README.md index 20b9f854..2eb721eb 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ If you have any suggestions or tips do not hesitate to open an issue or a PR. [![downloads](https://img.shields.io/crates/d/dashmap)](https://crates.io/crates/dashmap) -[![minimum rustc version](https://img.shields.io/badge/rustc-1.64-orange.svg)](https://crates.io/crates/dashmap) +[![minimum rustc version](https://img.shields.io/badge/rustc-1.65-orange.svg)](https://crates.io/crates/dashmap) ## Cargo features diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 3eca0d4d..a32876aa 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "stable-2022-09-22" +channel = "1.65" components = ["rustfmt", "clippy"] profile = "minimal" From 626b98dab3c124cd9cd4960d0306da5d65918dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Tue, 29 Aug 2023 23:13:21 +0200 Subject: [PATCH 9/9] v5.5.3 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb38a546..85bcb1b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.2" +version = "5.5.3" dependencies = [ "arbitrary", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 4d77d168..602ea9c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dashmap" -version = "5.5.2" +version = "5.5.3" authors = ["Acrimon "] edition = "2018" rust-version = "1.65"