[quagga-dev 8196] [PATCH 1/3] Better hashing of string values

Stephen Hemminger shemminger at vyatta.com
Fri Aug 27 22:11:14 BST 2010


Replace simple additive hash with a hash function with better
distribution.  For more information on hash functions see:
   http://www.eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx

Signed-off-by: Stephen Hemminger <shemminger at vyatta.com>
---
This patch is NOT in latest Vyatta release, but has passed
regression test for next release.

 lib/distribute.c |   13 ++++---------
 lib/hash.c       |   11 +++++++++++
 lib/hash.h       |    2 ++
 lib/if_rmap.c    |    9 ++-------
 4 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/lib/distribute.c b/lib/distribute.c
index 242a225..420849d 100644
--- a/lib/distribute.c
+++ b/lib/distribute.c
@@ -114,16 +114,11 @@ distribute_get (const char *ifname)
 }
 
 static unsigned int
-distribute_hash_make (struct distribute *dist)
+distribute_hash_make (void *arg)
 {
-  unsigned int i, key;
+  const struct distribute *dist = arg;
 
-  key = 0;
-  if (dist->ifname)
-    for (i = 0; i < strlen (dist->ifname); i++)
-      key += dist->ifname[i];
-
-  return key;
+  return dist->ifname ? string_hash_make (dist->ifname) : 0;
 }
 
 /* If two distribute-list have same value then return 1 else return
@@ -763,7 +758,7 @@ distribute_list_reset ()
 void
 distribute_list_init (int node)
 {
-  disthash = hash_create ((unsigned int (*) (void *)) distribute_hash_make,
+  disthash = hash_create (distribute_hash_make,
                           (int (*) (const void *, const void *)) distribute_cmp);
 
   if(node==RIP_NODE) {
diff --git a/lib/hash.c b/lib/hash.c
index 672327e..6db79ea 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -101,6 +101,17 @@ hash_lookup (struct hash *hash, void *data)
   return hash_get (hash, data, NULL);
 }
 
+/* Simple Bernstein hash which is simple and fast for common case */
+unsigned int string_hash_make (const char *str)
+{
+  unsigned int hash = 0;
+
+  while (*str)
+    hash = (hash * 33) ^ (unsigned int) *str++;
+
+  return hash;
+}
+
 /* This function release registered value from specified hash.  When
    release is successfully finished, return the data pointer in the
    hash backet.  */
diff --git a/lib/hash.h b/lib/hash.h
index f4b1c23..4cb772e 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -70,4 +70,6 @@ extern void hash_iterate (struct hash *,
 extern void hash_clean (struct hash *, void (*) (void *));
 extern void hash_free (struct hash *);
 
+extern unsigned int string_hash_make (const char *);
+
 #endif /* _ZEBRA_HASH_H */
diff --git a/lib/if_rmap.c b/lib/if_rmap.c
index ddc62fd..9774be4 100644
--- a/lib/if_rmap.c
+++ b/lib/if_rmap.c
@@ -109,14 +109,9 @@ if_rmap_get (const char *ifname)
 static unsigned int
 if_rmap_hash_make (void *data)
 {
-  struct if_rmap *if_rmap = data;
-  unsigned int i, key;
+  const struct if_rmap *if_rmap = data;
 
-  key = 0;
-  for (i = 0; i < strlen (if_rmap->ifname); i++)
-    key += if_rmap->ifname[i];
-
-  return key;
+  return string_hash_make (if_rmap->ifname);
 }
 
 static int
-- 
1.7.0.4




More information about the Quagga-dev mailing list