tag/Pool: use doubly-linked list

This adds some memory overhead but eliminates the linear search from
tag_pool_put_item().
This commit is contained in:
Max Kellermann 2023-09-06 15:56:10 +02:00
parent b896711fc6
commit 44beae519d

View File

@ -4,7 +4,7 @@
#include "Pool.hxx" #include "Pool.hxx"
#include "Item.hxx" #include "Item.hxx"
#include "util/Cast.hxx" #include "util/Cast.hxx"
#include "util/IntrusiveForwardList.hxx" #include "util/IntrusiveList.hxx"
#include "util/VarSize.hxx" #include "util/VarSize.hxx"
#include <array> #include <array>
@ -18,7 +18,7 @@
Mutex tag_pool_lock; Mutex tag_pool_lock;
struct TagPoolSlot { struct TagPoolSlot {
IntrusiveForwardListHook list_hook; IntrusiveListHook<IntrusiveHookMode::NORMAL> list_hook;
uint8_t ref = 1; uint8_t ref = 1;
TagItem item; TagItem item;
@ -45,8 +45,8 @@ TagPoolSlot::Create(TagType type,
value); value);
} }
static std::array<IntrusiveForwardList<TagPoolSlot, static std::array<IntrusiveList<TagPoolSlot,
IntrusiveForwardListMemberHookTraits<&TagPoolSlot::list_hook>>, IntrusiveListMemberHookTraits<&TagPoolSlot::list_hook>>,
16127> slots; 16127> slots;
static inline unsigned static inline unsigned
@ -60,19 +60,6 @@ calc_hash(TagType type, std::string_view p) noexcept
return hash ^ type; return hash ^ type;
} }
static inline unsigned
calc_hash(TagType type, const char *p) noexcept
{
unsigned hash = 5381;
assert(p != nullptr);
while (*p != 0)
hash = (hash << 5) + hash + *p++;
return hash ^ type;
}
static constexpr TagPoolSlot * static constexpr TagPoolSlot *
tag_item_to_slot(TagItem *item) noexcept tag_item_to_slot(TagItem *item) noexcept
{ {
@ -85,20 +72,12 @@ tag_value_list(TagType type, std::string_view value) noexcept
return slots[calc_hash(type, value) % slots.size()]; return slots[calc_hash(type, value) % slots.size()];
} }
static inline auto &
tag_value_list(TagType type, const char *value) noexcept
{
return slots[calc_hash(type, value) % slots.size()];
}
TagItem * TagItem *
tag_pool_get_item(TagType type, std::string_view value) noexcept tag_pool_get_item(TagType type, std::string_view value) noexcept
{ {
auto &list = tag_value_list(type, value); auto &list = tag_value_list(type, value);
for (auto i = list.before_begin(), n = std::next(i); n != list.end(); i = n) { for (auto &slot : list) {
auto &slot = *n++;
if (slot.item.type == type && if (slot.item.type == type &&
value == slot.item.value && value == slot.item.value &&
slot.ref < TagPoolSlot::MAX_REF) { slot.ref < TagPoolSlot::MAX_REF) {
@ -141,18 +120,6 @@ tag_pool_put_item(TagItem *item) noexcept
if (slot->ref > 0) if (slot->ref > 0)
return; return;
auto &list = tag_value_list(item->type, item->value); slot->list_hook.unlink();
for (auto i = list.before_begin();;) {
const auto n = std::next(i);
auto &s = *n;
assert(i != list.end());
if (&s == slot) {
list.erase_after(i);
DeleteVarSize(slot); DeleteVarSize(slot);
return;
}
i = n;
}
} }