From 4a67038e563385e8fffd2d0ea76f200c47c772aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 21 Jan 2008 19:57:40 +0000 Subject: [PATCH] * Added a new function hash_insert_grow() that grows the hash table when needed. * Removed the public hash_grow() function again (at least for now, it's only private). * Removed the newSize argument from hash_grow(); it will compute the new size automatically. * The block cache is now using hash_insert_grow() instead of hash_insert() which should make hash lookups much faster with some 10 thousand blocks, also increased the initial table size from 32 to 1024... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23692 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/util/khash.h | 4 +- src/system/kernel/cache/block_cache.cpp | 8 +- src/system/kernel/util/khash.c | 148 +++++++++++++----------- 3 files changed, 89 insertions(+), 71 deletions(-) diff --git a/headers/private/kernel/util/khash.h b/headers/private/kernel/util/khash.h index ed23bed61b..52b36479c3 100644 --- a/headers/private/kernel/util/khash.h +++ b/headers/private/kernel/util/khash.h @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007, Haiku Inc. All rights reserved. + * Copyright 2002-2008, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -28,8 +28,8 @@ struct hash_table *hash_init(uint32 table_size, int next_ptr_offset, int compare_func(void *element, const void *key), uint32 hash_func(void *element, const void *key, uint32 range)); int hash_uninit(struct hash_table *table); -status_t hash_grow(struct hash_table *table, uint32 newSize); status_t hash_insert(struct hash_table *table, void *_element); +status_t hash_insert_grow(struct hash_table *table, void *_element); status_t hash_remove(struct hash_table *table, void *_element); void hash_remove_current(struct hash_table *table, struct hash_iterator *iterator); void *hash_remove_first(struct hash_table *table, uint32 *_cookie); diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp index 2e9b21bc5b..0d3dd706c6 100644 --- a/src/system/kernel/cache/block_cache.cpp +++ b/src/system/kernel/cache/block_cache.cpp @@ -327,7 +327,7 @@ block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize, if (buffer_cache == NULL) return; - hash = hash_init(32, 0, &cached_block::Compare, &cached_block::Hash); + hash = hash_init(1024, 0, &cached_block::Compare, &cached_block::Hash); if (hash == NULL) return; @@ -650,7 +650,7 @@ get_cached_block(block_cache *cache, off_t blockNumber, bool *_allocated, if (block == NULL) return NULL; - hash_insert(cache->hash, block); + hash_insert_grow(cache->hash, block); *_allocated = true; } @@ -1118,7 +1118,7 @@ cache_start_transaction(void *_cache) TRACE(("cache_start_transaction(): id %ld started\n", transaction->id)); T(Action("start", cache, transaction)); - hash_insert(cache->transaction_hash, transaction); + hash_insert_grow(cache->transaction_hash, transaction); return transaction->id; } @@ -1347,7 +1347,7 @@ cache_detach_sub_transaction(void *_cache, int32 id, transaction->num_blocks = transaction->main_num_blocks; transaction->sub_num_blocks = 0; - hash_insert(cache->transaction_hash, newTransaction); + hash_insert_grow(cache->transaction_hash, newTransaction); cache->last_transaction = newTransaction; return newTransaction->id; diff --git a/src/system/kernel/util/khash.c b/src/system/kernel/util/khash.c index 8f34a42379..43ebf4d6f6 100644 --- a/src/system/kernel/util/khash.c +++ b/src/system/kernel/util/khash.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007, Haiku Inc. All rights reserved. + * Copyright 2002-2008, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Copyright 2001, Travis Geiselbrecht. All rights reserved. @@ -72,63 +72,10 @@ next_element(hash_table *table, void *element) } -struct hash_table * -hash_init(uint32 table_size, int next_ptr_offset, - int compare_func(void *e, const void *key), - uint32 hash_func(void *e, const void *key, uint32 range)) -{ - struct hash_table *t; - unsigned int i; - - table_size = get_prime_table_size(table_size); - - if (compare_func == NULL || hash_func == NULL) { - dprintf("hash_init() called with NULL function pointer\n"); - return NULL; - } - - t = (struct hash_table *)malloc(sizeof(struct hash_table)); - if (t == NULL) - return NULL; - - t->table = (struct hash_element **)malloc(sizeof(void *) * table_size); - if (t->table == NULL) { - free(t); - return NULL; - } - - for (i = 0; i < table_size; i++) - t->table[i] = NULL; - - t->table_size = table_size; - t->next_ptr_offset = next_ptr_offset; - t->flags = 0; - t->num_elements = 0; - t->compare_func = compare_func; - t->hash_func = hash_func; - - TRACE(("hash_init: created table %p, next_ptr_offset %d, compare_func %p, hash_func %p\n", - t, next_ptr_offset, compare_func, hash_func)); - - return t; -} - - -int -hash_uninit(struct hash_table *table) -{ - ASSERT(table->num_elements == 0); - - free(table->table); - free(table); - - return 0; -} - - -status_t -hash_grow(struct hash_table *table, uint32 newSize) +static status_t +hash_grow(struct hash_table *table) { + uint32 newSize = get_prime_table_size(table->num_elements); struct hash_element **newTable; uint32 index; void *start; @@ -138,12 +85,10 @@ hash_grow(struct hash_table *table, uint32 newSize) return B_OK; newTable = (struct hash_element **)malloc(sizeof(void *) * newSize); - if (newTable == NULL) return B_NO_MEMORY; - for (index = 0; index < newSize; index++) - newTable[index] = NULL; + memset(newTable, 0, sizeof(void *) * newSize); // rehash all the entries and add them to the new table for (index = 0; index < table->table_size; index++) { @@ -168,6 +113,63 @@ hash_grow(struct hash_table *table, uint32 newSize) } +// #pragma mark - kernel private API + + +struct hash_table * +hash_init(uint32 tableSize, int nextPointerOffset, + int compareFunc(void *e, const void *key), + uint32 hashFunc(void *e, const void *key, uint32 range)) +{ + struct hash_table *t; + uint32 i; + + tableSize = get_prime_table_size(tableSize); + + if (compareFunc == NULL || hashFunc == NULL) { + dprintf("hash_init() called with NULL function pointer\n"); + return NULL; + } + + t = (struct hash_table *)malloc(sizeof(struct hash_table)); + if (t == NULL) + return NULL; + + t->table = (struct hash_element **)malloc(sizeof(void *) * tableSize); + if (t->table == NULL) { + free(t); + return NULL; + } + + for (i = 0; i < tableSize; i++) + t->table[i] = NULL; + + t->table_size = tableSize; + t->next_ptr_offset = nextPointerOffset; + t->flags = 0; + t->num_elements = 0; + t->compare_func = compareFunc; + t->hash_func = hashFunc; + + TRACE(("hash_init: created table %p, next_ptr_offset %d, compare_func %p, hash_func %p\n", + t, nextPointerOffset, compareFunc, hashFunc)); + + return t; +} + + +int +hash_uninit(struct hash_table *table) +{ + ASSERT(table->num_elements == 0); + + free(table->table); + free(table); + + return 0; +} + + status_t hash_insert(struct hash_table *table, void *element) { @@ -181,11 +183,27 @@ hash_insert(struct hash_table *table, void *element) table->table[hash] = (struct hash_element *)element; table->num_elements++; - // ToDo: resize hash table if it's grown too much! - /*if ((uint32)table->num_elements > table->table_size * 4) { - dprintf("hash_insert: table has grown too much: %d in %d\n", table->num_elements, (int)table->table_size); - hash_grow(table, (uint32)table->num_elements); - }*/ + return B_OK; +} + + +status_t +hash_insert_grow(struct hash_table *table, void *element) +{ + uint32 hash; + + ASSERT(table != NULL && element != NULL); + TRACE(("hash_insert_grow: table %p, element %p\n", table, element)); + + hash = table->hash_func(element, NULL, table->table_size); + PUT_IN_NEXT(table, element, table->table[hash]); + table->table[hash] = (struct hash_element *)element; + table->num_elements++; + + if ((uint32)table->num_elements > table->table_size) { + //dprintf("hash_insert: table has grown too much: %d in %d\n", table->num_elements, (int)table->table_size); + hash_grow(table); + } return B_OK; }