From 73ade8cc43e4bfa554f4cc13881fd21ab6d94dd8 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 23 Feb 2022 16:27:19 +0300 Subject: [PATCH] Randomize hash value and optimize bucket calculation. --- tdutils/td/utils/FlatHashMapChunks.h | 3 +-- tdutils/td/utils/FlatHashMapLinear.h | 27 +++++++++++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/tdutils/td/utils/FlatHashMapChunks.h b/tdutils/td/utils/FlatHashMapChunks.h index 05aab59fd..857c66722 100644 --- a/tdutils/td/utils/FlatHashMapChunks.h +++ b/tdutils/td/utils/FlatHashMapChunks.h @@ -483,8 +483,7 @@ class FlatHashTableChunks { } HashInfo calc_hash(const KeyT &key) { - auto h = HashT()(key); - // TODO: will be problematic with current hash. + auto h = randomize_hash(HashT()(key)); return {(h >> 8) % chunks_.size(), static_cast(0x80 | h)}; } diff --git a/tdutils/td/utils/FlatHashMapLinear.h b/tdutils/td/utils/FlatHashMapLinear.h index 678dd3d4f..089a87c74 100644 --- a/tdutils/td/utils/FlatHashMapLinear.h +++ b/tdutils/td/utils/FlatHashMapLinear.h @@ -18,12 +18,22 @@ #include namespace td { -// TODO: move + template bool is_key_empty(const KeyT &key) { return key == KeyT(); } +inline uint32 randomize_hash(size_t h) { + auto result = static_cast(h & 0xFFFFFFFF); + result ^= result >> 16; + result *= 0x85ebca6b; + result ^= result >> 13; + result *= 0xc2b2ae35; + result ^= result >> 16; + return result; +} + template struct MapNode { using first_type = KeyT; @@ -485,8 +495,8 @@ class FlatHashTable { resize(want_size); } - size_t calc_bucket(const KeyT &key) const { - return HashT()(key) % nodes_.size(); + uint32 calc_bucket(const KeyT &key) const { + return randomize_hash(HashT()(key)) & static_cast(nodes_.size() - 1); } void resize(size_t new_size) { @@ -497,7 +507,7 @@ class FlatHashTable { if (old_node.empty()) { continue; } - size_t bucket = calc_bucket(old_node.key()); + auto bucket = calc_bucket(old_node.key()); while (!nodes_[bucket].empty()) { next_bucket(bucket); } @@ -505,11 +515,8 @@ class FlatHashTable { } } - void next_bucket(size_t &bucket) const { - bucket++; - if (unlikely(bucket == nodes_.size())) { - bucket = 0; - } + void next_bucket(uint32 &bucket) const { + bucket = (bucket + 1) & static_cast(nodes_.size() - 1); } void erase_node(NodeIterator it) { @@ -531,7 +538,7 @@ class FlatHashTable { auto want_i = calc_bucket(nodes_[test_bucket].key()); if (want_i < empty_i) { - want_i += nodes_.size(); + want_i += static_cast(nodes_.size()); } if (want_i <= empty_i || want_i > test_i) {