util/hash_table: 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 17f8e56c96
commit 41042f7fa2
2 changed files with 29 additions and 8 deletions

View File

@ -234,6 +234,13 @@ _mesa_hash_table_destroy(struct hash_table *ht,
ralloc_free(ht);
}
static void
hash_table_clear_fast(struct hash_table *ht)
{
memset(ht->table, 0, sizeof(struct hash_entry) * hash_sizes[ht->size_index].size);
ht->entries = ht->deleted_entries = 0;
}
/**
* Deletes all entries of the given hash table without deleting the table
* itself or changing its structure.
@ -249,15 +256,17 @@ _mesa_hash_table_clear(struct hash_table *ht,
struct hash_entry *entry;
for (entry = ht->table; entry != ht->table + ht->size; entry++) {
if (entry_is_present(ht, entry) && delete_function != NULL)
delete_function(entry);
if (delete_function) {
for (entry = ht->table; entry != ht->table + ht->size; entry++) {
if (entry_is_present(ht, entry))
delete_function(entry);
entry->key = NULL;
}
ht->entries = 0;
ht->deleted_entries = 0;
entry->key = NULL;
}
ht->entries = 0;
ht->deleted_entries = 0;
} else
hash_table_clear_fast(ht);
}
/** Sets the value of the key pointer used for deleted entries in the table.
@ -362,6 +371,12 @@ _mesa_hash_table_rehash(struct hash_table *ht, unsigned new_size_index)
struct hash_table old_ht;
struct hash_entry *table;
if (ht->size_index == new_size_index && ht->deleted_entries == ht->max_entries) {
hash_table_clear_fast(ht);
assert(!ht->entries);
return;
}
if (new_size_index >= ARRAY_SIZE(hash_sizes))
return;

View File

@ -86,6 +86,12 @@ int main()
hash_table_foreach(ht, entry) {
assert(key_id(entry->key) < SIZE);
}
_mesa_hash_table_clear(ht, NULL);
assert(!ht->entries);
assert(!ht->deleted_entries);
hash_table_foreach(ht, entry) {
assert(0);
}
_mesa_hash_table_destroy(ht, NULL);