From a3afd5178c249a7799881598379b9230ae75616a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 14 Mar 2016 13:08:04 +0100 Subject: [PATCH] tag/TagPool: optimize _dup_item() When a reference counter is at its limit, don't allocate a new TagPoolSlot - that would result in many TagPoolSlot instances with ref==1. This in turn would make the linked list very very large, which means quadratic runtime for many operations. --- NEWS | 1 + src/tag/TagPool.cxx | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 62ea0c08e..120557636 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ ver 0.19.14 (not yet released) - opus: limit tag size to 64 kB * archive - iso9660: fix buffer overflow +* fix quadratic runtime bug in the tag pool * fix build failures on non-glibc builds due to constexpr Mutex ver 0.19.13 (2016/02/23) diff --git a/src/tag/TagPool.cxx b/src/tag/TagPool.cxx index 55655cb54..97015b497 100644 --- a/src/tag/TagPool.cxx +++ b/src/tag/TagPool.cxx @@ -144,14 +144,10 @@ tag_pool_dup_item(TagItem *item) return item; } else { /* the reference counter overflows above MAX_REF; - duplicate the item, and start with 1 */ + obtain a reference to a different TagPoolSlot which + isn't yet "full" */ size_t length = strlen(item->value); - auto slot_p = tag_value_slot_p(item->type, - item->value, length); - slot = TagPoolSlot::Create(*slot_p, item->type, - item->value, strlen(item->value)); - *slot_p = slot; - return &slot->item; + return tag_pool_get_item(item->type, item->value, length); } }