mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-28 13:43:45 +03:00
AK: Inline HashTable writing bucket lookup
The old approach was more complex and also had a very bad edge case with lots of collisions. This approach eliminates that possiblility. It also makes both reading and writing lookups a little bit faster.
This commit is contained in:
parent
509eb10df4
commit
e55b8712d4
Notes:
sideshowbarker
2024-07-18 20:54:19 +09:00
Author: https://github.com/thislooksfun Commit: https://github.com/SerenityOS/serenity/commit/e55b8712d48 Pull-request: https://github.com/SerenityOS/serenity/pull/6070
@ -304,7 +304,7 @@ private:
|
||||
}
|
||||
|
||||
template<typename Finder>
|
||||
Bucket* lookup_with_hash(unsigned hash, Finder finder, Bucket** usable_bucket_for_writing = nullptr) const
|
||||
Bucket* lookup_with_hash(unsigned hash, Finder finder) const
|
||||
{
|
||||
if (is_empty())
|
||||
return nullptr;
|
||||
@ -312,10 +312,6 @@ private:
|
||||
for (;;) {
|
||||
auto& bucket = m_buckets[hash % m_capacity];
|
||||
|
||||
if (usable_bucket_for_writing && !*usable_bucket_for_writing && !bucket.used) {
|
||||
*usable_bucket_for_writing = &bucket;
|
||||
}
|
||||
|
||||
if (bucket.used && finder(*bucket.slot()))
|
||||
return &bucket;
|
||||
|
||||
@ -333,25 +329,25 @@ private:
|
||||
|
||||
Bucket& lookup_for_writing(const T& value)
|
||||
{
|
||||
auto hash = TraitsForT::hash(value);
|
||||
Bucket* usable_bucket_for_writing = nullptr;
|
||||
if (auto* bucket_for_reading = lookup_with_hash(
|
||||
hash,
|
||||
[&value](auto& entry) { return TraitsForT::equals(entry, value); },
|
||||
&usable_bucket_for_writing)) {
|
||||
return *const_cast<Bucket*>(bucket_for_reading);
|
||||
}
|
||||
|
||||
if (should_grow())
|
||||
rehash(capacity() * 2);
|
||||
else if (usable_bucket_for_writing)
|
||||
return *usable_bucket_for_writing;
|
||||
|
||||
|
||||
auto hash = TraitsForT::hash(value);
|
||||
Bucket* first_empty_bucket = nullptr;
|
||||
for (;;) {
|
||||
auto& bucket = m_buckets[hash % m_capacity];
|
||||
if (!bucket.used)
|
||||
|
||||
if (bucket.used && TraitsForT::equals(*bucket.slot(), value))
|
||||
return bucket;
|
||||
|
||||
if (!bucket.used) {
|
||||
if (!first_empty_bucket)
|
||||
first_empty_bucket = &bucket;
|
||||
|
||||
if (!bucket.deleted)
|
||||
return *const_cast<Bucket*>(first_empty_bucket);
|
||||
}
|
||||
|
||||
hash = double_hash(hash);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user