Micro-optimize hash table probing
All checks were successful
Run tests / Run tests (push) Successful in 7m6s
All checks were successful
Run tests / Run tests (push) Successful in 7m6s
This commit is contained in:
parent
6601824986
commit
aea5de0f6a
1 changed files with 28 additions and 17 deletions
|
|
@ -18,6 +18,25 @@ namespace psemek::util
|
|||
constexpr std::uint64_t tombstone_mask = 1ull << 62;
|
||||
constexpr std::uint64_t hash_value_mask = ~(stored_value_mask | tombstone_mask);
|
||||
|
||||
struct indexer
|
||||
{
|
||||
std::size_t index;
|
||||
std::size_t capacity;
|
||||
std::size_t step = 0;
|
||||
|
||||
indexer(std::size_t index, std::size_t capacity)
|
||||
: index{index & (capacity - 1)}
|
||||
, capacity{capacity}
|
||||
{}
|
||||
|
||||
void next()
|
||||
{
|
||||
step += 1;
|
||||
index += step;
|
||||
index &= (capacity - 1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct hash_table_entry
|
||||
{
|
||||
|
|
@ -331,42 +350,34 @@ namespace psemek::util
|
|||
reallocate(capacity());
|
||||
}
|
||||
|
||||
std::size_t probe_index(std::uint64_t hash, std::size_t i) const
|
||||
{
|
||||
return (static_cast<std::size_t>(hash) + (i * (i + 1)) / 2) % storage_.capacity;
|
||||
}
|
||||
|
||||
template <typename H>
|
||||
std::pair<hash_table_iterator<T>, bool> insert_impl(H && value, std::uint64_t hash)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
struct indexer indexer{hash, storage_.capacity};
|
||||
while (true)
|
||||
{
|
||||
std::size_t index = probe_index(hash, i);
|
||||
auto & entry = storage_.table[index];
|
||||
auto & entry = storage_.table[indexer.index];
|
||||
if (!entry.has_value() || entry.is_tombstone())
|
||||
{
|
||||
entry.set_value(std::forward<H>(value), hash);
|
||||
++size_;
|
||||
return {storage_.iterator(index), true};
|
||||
return {storage_.iterator(indexer.index), true};
|
||||
}
|
||||
else if (entry.hash_equal(hash) && equal()(key_projector()(value), key_projector()(entry.value())))
|
||||
{
|
||||
return {storage_.iterator(index), false};
|
||||
return {storage_.iterator(indexer.index), false};
|
||||
}
|
||||
else
|
||||
++i;
|
||||
indexer.next();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
hash_table_iterator<T> find_impl(Key const & key, std::uint64_t hash) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
struct indexer indexer{hash, storage_.capacity};
|
||||
while (true)
|
||||
{
|
||||
std::size_t index = probe_index(hash, i);
|
||||
auto & entry = storage_.table[index];
|
||||
auto & entry = storage_.table[indexer.index];
|
||||
if (!entry.is_tombstone())
|
||||
{
|
||||
if (!entry.has_value())
|
||||
|
|
@ -375,10 +386,10 @@ namespace psemek::util
|
|||
}
|
||||
else if (entry.hash_equal(hash) && equal()(key, key_projector()(entry.value())))
|
||||
{
|
||||
return storage_.iterator(index);
|
||||
return storage_.iterator(indexer.index);
|
||||
}
|
||||
}
|
||||
++i;
|
||||
indexer.next();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue