Change hash mixing and add distance_histogram method

This commit is contained in:
Gwilym Inzani 2023-05-10 17:49:48 +01:00
parent 1fa4d8e970
commit 65dd1341e5
2 changed files with 38 additions and 10 deletions

View file

@ -26,7 +26,7 @@
extern crate alloc;
use alloc::alloc::Global;
use alloc::{alloc::Global, vec::Vec};
use core::{
alloc::Allocator,
borrow::Borrow,
@ -174,6 +174,12 @@ impl<K, V> HashMap<K, V> {
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_in(capacity, Global)
}
#[doc(hidden)]
#[must_use]
pub fn distance_histogram(&self) -> (Vec<usize>, usize) {
self.nodes.distance_histogram()
}
}
impl<K, V, ALLOCATOR: ClonableAllocator> HashMap<K, V, ALLOCATOR> {
@ -898,7 +904,7 @@ where
}
const fn number_before_resize(capacity: usize) -> usize {
capacity * 85 / 100
capacity * 60 / 100
}
#[derive(Default, Clone, Copy, PartialEq, Eq)]
@ -915,12 +921,18 @@ impl From<usize> for HashType {
impl HashType {
// 32 bit mix function from here: https://gist.github.com/badboy/6267743
fn bit_mix(key: u32) -> Self {
let key = !key.wrapping_add(key << 15);
let key = key ^ key.rotate_right(12);
let key = key.wrapping_add(key << 2);
let key = key ^ key.rotate_right(4);
let key = key.wrapping_add(key << 3).wrapping_add(key << 11);
Self(key ^ key.rotate_right(16))
use core::num::Wrapping;
let key = Wrapping(key);
let key = (key + Wrapping(0x7ed55d16u32)) + (key << 12);
let key = (key ^ Wrapping(0xc761c23c)) ^ (key >> 19);
let key = (key + Wrapping(0x165667b1)) + (key << 5);
let key = (key + Wrapping(0xd3a2646c)) ^ (key << 9);
let key = (key + Wrapping(0xfd7046c5)) + (key << 3);
let key = (key ^ Wrapping(0xb55a4f09)) ^ (key >> 16);
Self(key.0)
}
pub(crate) fn fast_mod(self, len: usize) -> usize {
@ -1085,9 +1097,9 @@ mod test {
let mut map = HashMap::new();
let mut rng = rand::rngs::SmallRng::seed_from_u64(20);
let mut answers: [Option<i32>; 128] = [None; 128];
let mut answers: [Option<i32>; 512] = [None; 512];
for _ in 0..5_000 {
for _ in 0..15_000 {
let command = rng.next_i32().rem_euclid(2);
let key = rng.next_i32().rem_euclid(answers.len().try_into().unwrap());
let value = rng.next_i32();

View file

@ -194,4 +194,20 @@ impl<K, V, ALLOCATOR: ClonableAllocator> NodeStorage<K, V, ALLOCATOR> {
pub(crate) unsafe fn node_at_unchecked_mut(&mut self, at: usize) -> &mut Node<K, V> {
self.nodes.get_unchecked_mut(at)
}
pub(crate) fn distance_histogram(&self) -> (Vec<usize>, usize) {
let mut ret = Vec::new();
for node in self.nodes.iter() {
let distance = node.distance();
if distance >= 0 {
let distance = distance as usize;
ret.resize(ret.len().max(distance + 1), 0);
ret[distance] += 1;
}
}
(ret, self.max_distance_to_initial_bucket as usize)
}
}