From 41042f7fa29787347a4844a06a60b0c83fc916c1 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 12 Jan 2021 12:20:41 -0500 Subject: [PATCH] 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 Part-of: --- src/util/hash_table.c | 31 +++++++++++++++++++++++-------- src/util/tests/hash_table/clear.c | 6 ++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/util/hash_table.c b/src/util/hash_table.c index 9ca0d5e2d64..92897c1bc83 100644 --- a/src/util/hash_table.c +++ b/src/util/hash_table.c @@ -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; diff --git a/src/util/tests/hash_table/clear.c b/src/util/tests/hash_table/clear.c index e61f60ece1b..90ca30e3a1c 100644 --- a/src/util/tests/hash_table/clear.c +++ b/src/util/tests/hash_table/clear.c @@ -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);