mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-31 04:43:06 +02:00
cache the value of the hash function in the GHashNode. this speeds up
2006-12-27 Ryan Lortie <desrt@desrt.ca> * glib/ghash.c: cache the value of the hash function in the GHashNode. this speeds up resizing the hash table and it also allows a slight optimisation on lookups. (#388332)
This commit is contained in:
parent
d1be55cccb
commit
e6b78c9af1
@ -1,3 +1,10 @@
|
|||||||
|
2006-12-27 Ryan Lortie <desrt@desrt.ca>
|
||||||
|
|
||||||
|
* glib/ghash.c: cache the value of the hash function
|
||||||
|
in the GHashNode. this speeds up resizing the hash
|
||||||
|
table and it also allows a slight optimisation on
|
||||||
|
lookups. (#388332)
|
||||||
|
|
||||||
2006-12-27 Matthias Clasen <mclasen@redhat.com>
|
2006-12-27 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* glib/gunicollate.c (g_utf8_collate_key): Don't modify
|
* glib/gunicollate.c (g_utf8_collate_key): Don't modify
|
||||||
|
51
glib/ghash.c
51
glib/ghash.c
@ -44,6 +44,7 @@ struct _GHashNode
|
|||||||
{
|
{
|
||||||
gpointer key;
|
gpointer key;
|
||||||
gpointer value;
|
gpointer value;
|
||||||
|
guint key_hash;
|
||||||
GHashNode *next;
|
GHashNode *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -70,9 +71,11 @@ struct _GHashTable
|
|||||||
|
|
||||||
static void g_hash_table_resize (GHashTable *hash_table);
|
static void g_hash_table_resize (GHashTable *hash_table);
|
||||||
static GHashNode** g_hash_table_lookup_node (GHashTable *hash_table,
|
static GHashNode** g_hash_table_lookup_node (GHashTable *hash_table,
|
||||||
gconstpointer key);
|
gconstpointer key,
|
||||||
|
guint *hash_return);
|
||||||
static GHashNode* g_hash_node_new (gpointer key,
|
static GHashNode* g_hash_node_new (gpointer key,
|
||||||
gpointer value);
|
gpointer value,
|
||||||
|
guint key_hash);
|
||||||
static void g_hash_node_destroy (GHashNode *hash_node,
|
static void g_hash_node_destroy (GHashNode *hash_node,
|
||||||
GDestroyNotify key_destroy_func,
|
GDestroyNotify key_destroy_func,
|
||||||
GDestroyNotify value_destroy_func);
|
GDestroyNotify value_destroy_func);
|
||||||
@ -224,25 +227,35 @@ g_hash_table_destroy (GHashTable *hash_table)
|
|||||||
|
|
||||||
static inline GHashNode**
|
static inline GHashNode**
|
||||||
g_hash_table_lookup_node (GHashTable *hash_table,
|
g_hash_table_lookup_node (GHashTable *hash_table,
|
||||||
gconstpointer key)
|
gconstpointer key,
|
||||||
|
guint *hash_return)
|
||||||
{
|
{
|
||||||
GHashNode **node;
|
GHashNode **node;
|
||||||
|
guint hash_value;
|
||||||
|
|
||||||
|
hash_value = (* hash_table->hash_func) (key);
|
||||||
|
node = &hash_table->nodes[hash_value % hash_table->size];
|
||||||
|
|
||||||
node = &hash_table->nodes
|
if (hash_return)
|
||||||
[(* hash_table->hash_func) (key) % hash_table->size];
|
*hash_return = hash_value;
|
||||||
|
|
||||||
/* Hash table lookup needs to be fast.
|
/* Hash table lookup needs to be fast.
|
||||||
* We therefore remove the extra conditional of testing
|
* We therefore remove the extra conditional of testing
|
||||||
* whether to call the key_equal_func or not from
|
* whether to call the key_equal_func or not from
|
||||||
* the inner loop.
|
* the inner loop.
|
||||||
|
*
|
||||||
|
* Additional optimisation: first check if our full hash
|
||||||
|
* values are equal so we can avoid calling the full-blown
|
||||||
|
* key equality function in most cases.
|
||||||
*/
|
*/
|
||||||
if (hash_table->key_equal_func)
|
if (hash_table->key_equal_func)
|
||||||
while (*node && !(*hash_table->key_equal_func) ((*node)->key, key))
|
while (*node && (((*node)->key_hash != hash_value) ||
|
||||||
|
!(*hash_table->key_equal_func) ((*node)->key, key)))
|
||||||
node = &(*node)->next;
|
node = &(*node)->next;
|
||||||
else
|
else
|
||||||
while (*node && (*node)->key != key)
|
while (*node && (*node)->key != key)
|
||||||
node = &(*node)->next;
|
node = &(*node)->next;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +279,7 @@ g_hash_table_lookup (GHashTable *hash_table,
|
|||||||
|
|
||||||
g_return_val_if_fail (hash_table != NULL, NULL);
|
g_return_val_if_fail (hash_table != NULL, NULL);
|
||||||
|
|
||||||
node = *g_hash_table_lookup_node (hash_table, key);
|
node = *g_hash_table_lookup_node (hash_table, key, NULL);
|
||||||
|
|
||||||
return node ? node->value : NULL;
|
return node ? node->value : NULL;
|
||||||
}
|
}
|
||||||
@ -295,7 +308,7 @@ g_hash_table_lookup_extended (GHashTable *hash_table,
|
|||||||
|
|
||||||
g_return_val_if_fail (hash_table != NULL, FALSE);
|
g_return_val_if_fail (hash_table != NULL, FALSE);
|
||||||
|
|
||||||
node = *g_hash_table_lookup_node (hash_table, lookup_key);
|
node = *g_hash_table_lookup_node (hash_table, lookup_key, NULL);
|
||||||
|
|
||||||
if (node)
|
if (node)
|
||||||
{
|
{
|
||||||
@ -329,11 +342,12 @@ g_hash_table_insert (GHashTable *hash_table,
|
|||||||
gpointer value)
|
gpointer value)
|
||||||
{
|
{
|
||||||
GHashNode **node;
|
GHashNode **node;
|
||||||
|
guint key_hash;
|
||||||
|
|
||||||
g_return_if_fail (hash_table != NULL);
|
g_return_if_fail (hash_table != NULL);
|
||||||
g_return_if_fail (hash_table->ref_count > 0);
|
g_return_if_fail (hash_table->ref_count > 0);
|
||||||
|
|
||||||
node = g_hash_table_lookup_node (hash_table, key);
|
node = g_hash_table_lookup_node (hash_table, key, &key_hash);
|
||||||
|
|
||||||
if (*node)
|
if (*node)
|
||||||
{
|
{
|
||||||
@ -353,7 +367,7 @@ g_hash_table_insert (GHashTable *hash_table,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*node = g_hash_node_new (key, value);
|
*node = g_hash_node_new (key, value, key_hash);
|
||||||
hash_table->nnodes++;
|
hash_table->nnodes++;
|
||||||
G_HASH_TABLE_RESIZE (hash_table);
|
G_HASH_TABLE_RESIZE (hash_table);
|
||||||
}
|
}
|
||||||
@ -378,11 +392,12 @@ g_hash_table_replace (GHashTable *hash_table,
|
|||||||
gpointer value)
|
gpointer value)
|
||||||
{
|
{
|
||||||
GHashNode **node;
|
GHashNode **node;
|
||||||
|
guint key_hash;
|
||||||
|
|
||||||
g_return_if_fail (hash_table != NULL);
|
g_return_if_fail (hash_table != NULL);
|
||||||
g_return_if_fail (hash_table->ref_count > 0);
|
g_return_if_fail (hash_table->ref_count > 0);
|
||||||
|
|
||||||
node = g_hash_table_lookup_node (hash_table, key);
|
node = g_hash_table_lookup_node (hash_table, key, &key_hash);
|
||||||
|
|
||||||
if (*node)
|
if (*node)
|
||||||
{
|
{
|
||||||
@ -397,7 +412,7 @@ g_hash_table_replace (GHashTable *hash_table,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*node = g_hash_node_new (key, value);
|
*node = g_hash_node_new (key, value, key_hash);
|
||||||
hash_table->nnodes++;
|
hash_table->nnodes++;
|
||||||
G_HASH_TABLE_RESIZE (hash_table);
|
G_HASH_TABLE_RESIZE (hash_table);
|
||||||
}
|
}
|
||||||
@ -425,7 +440,7 @@ g_hash_table_remove (GHashTable *hash_table,
|
|||||||
|
|
||||||
g_return_val_if_fail (hash_table != NULL, FALSE);
|
g_return_val_if_fail (hash_table != NULL, FALSE);
|
||||||
|
|
||||||
node = g_hash_table_lookup_node (hash_table, key);
|
node = g_hash_table_lookup_node (hash_table, key, NULL);
|
||||||
if (*node)
|
if (*node)
|
||||||
{
|
{
|
||||||
dest = *node;
|
dest = *node;
|
||||||
@ -493,7 +508,7 @@ g_hash_table_steal (GHashTable *hash_table,
|
|||||||
|
|
||||||
g_return_val_if_fail (hash_table != NULL, FALSE);
|
g_return_val_if_fail (hash_table != NULL, FALSE);
|
||||||
|
|
||||||
node = g_hash_table_lookup_node (hash_table, key);
|
node = g_hash_table_lookup_node (hash_table, key, NULL);
|
||||||
if (*node)
|
if (*node)
|
||||||
{
|
{
|
||||||
dest = *node;
|
dest = *node;
|
||||||
@ -733,7 +748,7 @@ g_hash_table_resize (GHashTable *hash_table)
|
|||||||
{
|
{
|
||||||
next = node->next;
|
next = node->next;
|
||||||
|
|
||||||
hash_val = (* hash_table->hash_func) (node->key) % new_size;
|
hash_val = node->key_hash % new_size;
|
||||||
|
|
||||||
node->next = new_nodes[hash_val];
|
node->next = new_nodes[hash_val];
|
||||||
new_nodes[hash_val] = node;
|
new_nodes[hash_val] = node;
|
||||||
@ -746,12 +761,14 @@ g_hash_table_resize (GHashTable *hash_table)
|
|||||||
|
|
||||||
static GHashNode*
|
static GHashNode*
|
||||||
g_hash_node_new (gpointer key,
|
g_hash_node_new (gpointer key,
|
||||||
gpointer value)
|
gpointer value,
|
||||||
|
guint key_hash)
|
||||||
{
|
{
|
||||||
GHashNode *hash_node = g_slice_new (GHashNode);
|
GHashNode *hash_node = g_slice_new (GHashNode);
|
||||||
|
|
||||||
hash_node->key = key;
|
hash_node->key = key;
|
||||||
hash_node->value = value;
|
hash_node->value = value;
|
||||||
|
hash_node->key_hash = key_hash;
|
||||||
hash_node->next = NULL;
|
hash_node->next = NULL;
|
||||||
|
|
||||||
return hash_node;
|
return hash_node;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user