util/set: optimize rehash for empty table and no-func clears

if the table is filled with deleted entries, we don't need to rzalloc+free an identical
block of memory for the table, we can just memset the existing one

the same applies to table clears without a function passed in that the table
doesn't need to be iterated and can just be memset

Reviewed-by: Eric Anholt <eric@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8450>
This commit is contained in:
Mike Blumenkrantz 2021-01-12 12:20:41 -05:00 committed by Marge Bot
parent 41042f7fa2
commit 5f3f128088
2 changed files with 31 additions and 8 deletions

View File

@ -211,6 +211,14 @@ _mesa_set_destroy(struct set *ht, void (*delete_function)(struct set_entry *entr
ralloc_free(ht);
}
static void
set_clear_fast(struct set *ht)
{
memset(ht->table, 0, sizeof(struct set_entry) * hash_sizes[ht->size_index].size);
ht->entries = ht->deleted_entries = 0;
}
/**
* Clears all values from the given set.
*
@ -225,15 +233,17 @@ _mesa_set_clear(struct set *set, void (*delete_function)(struct set_entry *entry
struct set_entry *entry;
for (entry = set->table; entry != set->table + set->size; entry++) {
if (entry_is_present(entry) && delete_function != NULL)
delete_function(entry);
if (delete_function) {
for (entry = set->table; entry != set->table + set->size; entry++) {
if (entry_is_present(entry))
delete_function(entry);
entry->key = NULL;
}
set->entries = 0;
set->deleted_entries = 0;
entry->key = NULL;
}
set->entries = 0;
set->deleted_entries = 0;
} else
set_clear_fast(set);
}
/**
@ -314,6 +324,12 @@ set_rehash(struct set *ht, unsigned new_size_index)
struct set old_ht;
struct set_entry *table;
if (ht->size_index == new_size_index && ht->deleted_entries == ht->max_entries) {
set_clear_fast(ht);
assert(!ht->entries);
return;
}
if (new_size_index >= ARRAY_SIZE(hash_sizes))
return;

View File

@ -51,6 +51,13 @@ TEST(set, basic)
entry = _mesa_set_search(s, a);
EXPECT_FALSE(entry);
_mesa_set_clear(s, NULL);
EXPECT_EQ(s->entries, 0);
EXPECT_EQ(s->deleted_entries, 0);
set_foreach(s, he) {
GTEST_FAIL();
}
_mesa_set_destroy(s, NULL);
}