]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: Better hashing of string values using Bernstein hash
authorStephen Hemminger <shemminger@vyatta.com>
Fri, 27 Aug 2010 21:11:14 +0000 (14:11 -0700)
committerPaul Jakma <paul@quagga.net>
Mon, 21 Mar 2011 13:30:54 +0000 (13:30 +0000)
* hash.{h,c}: (string_hash_make) Hash optimised for strings, current
  implementation using Bernstein hash, which offers a good compromise
  between distribution and performance.
* distribute.c: (distribute_hash_make) use previous instead of additive
  string hash.
* if_rmap.c: (if_rmap_hash_make) ditto

lib/distribute.c
lib/hash.c
lib/hash.h
lib/if_rmap.c

index 242a225c2a32e6ebbaff2c01f0dc2ce54aeb8d78..420849da8a73bbdb76e0d0f265cb7a340d412f45 100644 (file)
@@ -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) {
index 672327ec5b990726e13212cfe4184efc3d054918..6db79ea77a6ba7c9d1b27702c9d755e69c766830 100644 (file)
@@ -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.  */
index f4b1c23eb5c0e63d9af687c0ea3f28b43e921a3a..4cb772e5797ee6ff209da2ccc73476dee03a7572 100644 (file)
@@ -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 */
index ddc62fd51b2ccc32d99fa7adfc7c3e98f3cface7..9774be4b2ebd6140dd9c9b8a80aa8749c80fa793 100644 (file)
@@ -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