#include <dpkg.h>
#include <dpkg-db.h>
-#define BINS (1 << 7)
- /* This must always be a power of two. If you change it
- * consider changing the per-character hashing factor (currently 5) too.
+#define BINS 8191
+ /* This must always be a prime for optimal performance.
+ * With 4093 buckets, we glean a 20% speedup, for 8191 buckets
+ * we get 23%. The nominal increase in memory usage is a mere
+ * sizeof(void*)*8063 (I.E. less than 32KB on 32bit systems)
*/
static struct pkginfo *bins[BINS];
static int npackages;
-static int hash(const char *name) {
- int v= 0;
- while (*name) { v *= 5; v += tolower(*name); name++; }
- return v;
-/* These results were achieved with 128 bins, and the list of packages
- * shown at the bottom of this file.
- */
-/* while (*name) { v *= 17; v += tolower(*name); name++; }
- * size 5 occurs 1 times
- * size 4 occurs 0 times
- * size 3 occurs 7 times
- * size 2 occurs 32 times
- * size 1 occurs 51 times
- * size 0 occurs 37 times
- */
-/* while (*name) { v *= 5; v += tolower(*name); name++; }
- * size 4 occurs 1 times
- * size 3 occurs 14 times
- * size 2 occurs 20 times
- * size 1 occurs 55 times
- * size 0 occurs 38 times
- */
-/* while (*name) { v *= 11; v += tolower(*name); name++; }
- * size 5 occurs 1 times
- * size 4 occurs 4 times
- * size 3 occurs 9 times
- * size 2 occurs 25 times
- * size 1 occurs 43 times
- * size 0 occurs 46 times
- */
-/* while (*name) { v *= 31; v += tolower(*name); name++; }
- * size 6 occurs 1 times
- * size 5 occurs 0 times
- * size 4 occurs 1 times
- * size 3 occurs 11 times
- * size 2 occurs 27 times
- * size 1 occurs 44 times
- * size 0 occurs 44 times
- */
-/* while (*name) { v *= 111; v += tolower(*name); name++; }
- * size 5 occurs 1 times
- * size 4 occurs 1 times
- * size 3 occurs 14 times
- * size 2 occurs 23 times
- * size 1 occurs 44 times
- * size 0 occurs 45 times
- */
-/* while (*name) { v += (v<<3); v += tolower(*name); name++; }
- * size 4 occurs 5 times
- * size 3 occurs 12 times
- * size 2 occurs 22 times
- * size 1 occurs 41 times
- * size 0 occurs 48 times
- */
-/* while (*name) { v *= 29; v += tolower(*name); name++; }
- * size 5 occurs 1 times
- * size 4 occurs 2 times
- * size 3 occurs 10 times
- * size 2 occurs 26 times
- * size 1 occurs 46 times
- * size 0 occurs 43 times
- */
-/* while (*name) { v *= 13; v += tolower(*name); name++; }
- * size 5 occurs 1 times
- * size 4 occurs 2 times
- * size 3 occurs 5 times
- * size 2 occurs 30 times
- * size 1 occurs 53 times
- * size 0 occurs 37 times
- */
+#define FNV_offset_basis 2166136261ul
+#define FNV_mixing_prime 16777619ul
+
+/* Fowler/Noll/Vo -- simple string hash.
+ * For more info, see http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ * */
+
+static unsigned int hash(const char *name) {
+ register unsigned int h = FNV_offset_basis;
+ register unsigned int p = FNV_mixing_prime;
+ while( *name ) {
+ h *= p;
+ h ^= *name++;
+ }
+ return h;
}
void blankversion(struct versionrevision *version) {
p= name;
while(*p) { *p= tolower(*p); p++; }
- pointerp= bins + (hash(name) & (BINS-1));
+ pointerp= bins + (hash(name) % (BINS));
while (*pointerp && strcasecmp((*pointerp)->name,name))
pointerp= &(*pointerp)->next;
if (*pointerp) { free(name); return *pointerp; }