time33 哈希函数,又叫 DJBX33A,Bernstein's hash

简介:

php, apache, perl, bsddb都使用time33哈希.

最简单的版本

  uint32_t time33( char  const *str,  int len) 
    
        unsigned long  hash = 0; 
        for (int i = 0; i < len; i++) 
            hash = hash *33 + (unsigned long) str[i]; 
        }
 
        return hash; 
    }

 

这个版本最可以体现time33的算法思路,够简单。

 

把乘法操作换成位操作

        unsigned  long time33( char  const *str,  int len) 
    
        unsigned long  hash = 0; 
        for (int i = 0; i < len; i++) 
            hash = ((hash <<5) + hash) + (unsigned long) str[i]; 
        }
 
        return hash; 
    }
 

59个字符1000 0000次运行(gcc没有开启优化,因为开了优化后两个函数的实际代码会一样)

第一个:

real    0m4.389s 
user    0m4.388s 
sys     0m0.000s

 

第二个:

real    0m4.137s 
user    0m4.120s 
sys     0m0.000s

 

 

gcc –O2优化后是

real    0m1.367s 
user    0m1.360s 
sys     0m0.000s

 

 

php版本

 

inline unsigned time33(char  const*str, int len) 

     unsigned long hash = 5381; 
      /*  variant with the hash unrolled eight times  */ 
      for (; len >= 8; len -= 8) { 
         hash = ((hash << 5) + hash) + *str++; 
         hash = ((hash << 5) + hash) + *str++; 
         hash = ((hash << 5) + hash) + *str++; 
         hash = ((hash << 5) + hash) + *str++; 
        hash = ((hash << 5) + hash) + *str++; 
        hash = ((hash << 5) + hash) + *str++; 
        hash = ((hash << 5) + hash) + *str++; 
        hash = ((hash << 5) + hash) + *str++; 
    } 
     switch (len) { 
         case 7: hash = ((hash << 5) + hash) + *str++;  /*  fallthrough  */ 
         case 6: hash = ((hash << 5) + hash) + *str++;  /*  fallthrough  */ 
         case 5: hash = ((hash << 5) + hash) + *str++;  /*  fallthrough  */ 
         case 4: hash = ((hash << 5) + hash) + *str++;  /*  fallthrough  */ 
         case 3: hash = ((hash << 5) + hash) + *str++;  /*  fallthrough  */ 
         case 2: hash = ((hash << 5) + hash) + *str++;  /*  fallthrough  */ 
         case 1: hash = ((hash << 5) + hash) + *str++;  break
         case 0:  break
    } 
     return hash; 

 

59个字符,1000 0000次

real    0m1.088s 
user    0m1.068s 
sys     0m0.000s

 

速度提升主要在循环展开, 对于短字符,这个是不明显的。

php版本的hash初始值是5381, 这个

 

Magic Constant 5381:

  1. odd number

  2. prime number

  3. deficient number

  4. 001/010/100/000/101 b

 

Apache版本

unsigned  long time33( char  const  *str,  int *len) 

    unsigned long hash = 0;

    const char *p=str; 
    if (*len<=0) 
        for(p = str; *p; p++) 
            hash = hash * 33 + *p; 
        }
 
        *len = p - str; 
    }
 
    else 
        int i = *len; 
        for (p = str;i; i--, p++) 
            hash = hash * 33 + *p; 
        }
 
    }
 
    return hash; 
}

 

测试结果

real    0m1.418s 
user    0m1.412s 
sys     0m0.004s

 

 

综上,我的改进版本

#define likely(x) __builtin_expect((x),1) 
#define unlikely(x) __builtin_expect((x),0) 
     // php版本 
    unsigned  long time33( char  const *str,  int len=-1) 
    
        unsigned long hash = 5381; 
        /* variant with the hash unrolled eight times */ 
        char const *p = str; 
        if (unlikely(len<0)) 
                for(; *p; p++) 
                    hash = hash * 33 + *p; 
                }
 
                return hash; 
        }


#define TIME33_HASH_MIXED_CH()  hash = ((hash<<5)+hash) + *p++ 
        for (; len >= 8; len -= 8) 
            TIME33_HASH_MIXED_CH(); //
            TIME33_HASH_MIXED_CH(); //
            TIME33_HASH_MIXED_CH(); //
            TIME33_HASH_MIXED_CH(); //
            TIME33_HASH_MIXED_CH(); //
            TIME33_HASH_MIXED_CH(); //
            TIME33_HASH_MIXED_CH(); //
            TIME33_HASH_MIXED_CH(); //
       }
 
       switch (len) 
           case 7: TIME33_HASH_MIXED_CH(); /* fallthrough */ 
           case 6: TIME33_HASH_MIXED_CH(); /* fallthrough */ 
           case 5: TIME33_HASH_MIXED_CH(); /* fallthrough */ 
           case 4: TIME33_HASH_MIXED_CH(); /* fallthrough */ 
           case 3: TIME33_HASH_MIXED_CH(); /* fallthrough */ 
           case 2: TIME33_HASH_MIXED_CH(); /* fallthrough */ 
           case 1: TIME33_HASH_MIXED_CH(); break
           case 0: break
       }
 
       return hash; 
   }


#undef TIME33_HASH_MIXED_CH

 

测试结果

real    0m1.072s 
user    0m1.064s 
sys     0m0.000s

测试过, 重复率在 1/2000。

 

为什么是33的倍数, PHP中注释是

DJBX33A (Daniel J. Bernstein, Times 33 with Addition)
  This  is Daniel J. Bernstein's popular `times 33' hash function  as
  posted by him years ago on comp.lang.c. It basically uses a function
  like ``hash(i) = hash(i-1) * 33 + str[i]''. This  is one of the best
  known hash functions  for strings. Because it  is both computed very
  fast and distributes very well.
  The magic of number 33, i.e. why it works better than many other
  constants, prime or not, has never been adequately explained by
  anyone. So I  try an explanation:  if one experimentally tests all
  multipliers between 1 and 256 ( as RSE did now) one detects that even
  numbers are not useable at all. The remaining 128 odd numbers
  (except  for the number 1) work more or less all equally well. They
  all distribute  in an acceptable way and  this way fill a hash table
  with an average percent of approx. 86%.
  If one compares the Chi^2 values of the variants, the number 33 not
  even has the best value. But the number 33 and a few other equally
  good numbers like 17, 31, 63, 127 and 129 have nevertheless a great
  advantage to the remaining numbers  in the large  set of possible
  multipliers: their multiply operation can be replaced by a faster
  operation based on just one shift plus either a single addition
  or subtraction operation. And because a hash function has to both
  distribute good _and_ has to be very fast to compute, those few
  numbers should be preferred and seems to be the reason why Daniel J.
  Bernstein also preferred it.
                   -- Ralf S. Engelschall rse@engelschall.com

 

 

其它倍数

Ngix使用的是 time31

Tokyo Cabinet使用的是 time37

Bob在他的文章说,小写英文词汇适合33, 大小写混合使用65。time33比较适合的是英文词汇的hash.

目录
相关文章
|
2月前
|
存储 负载均衡 算法
Hash介绍与应用详解
哈希算法在计算机科学中有着广泛而重要的应用,从数据存储、数据完整性校验到密码安全和分布式系统中的负载均衡,哈希函数都发挥着关键作用。通过本文的介绍和示例代码,希望您能更好地理解哈希的基本概念和实际应用,并在您的项目中有效地应用这些知识。
282 3
|
8月前
|
Shell
|
存储 算法 安全
Hash 算法详细介绍与实现 (二)
书接上回,昨天写了第一部分,《Hash 算法详细介绍与实现 (一)》详细介绍了Hash表和Hash算法的相关概念以及算法的基本原理。同时简单介绍几种hash算法的实现:直接取余法和乘法取整法;本文接着详细唠唠Hash算法和Hash表这个数据结构的具体实现以及Hash算法和Hash表常见问题的解决方案,比如解决Hash表的冲突问题等等.相关的理论知识已在上篇文章详细介绍,这里就不再赘述,多的不说少的不唠,直接进入今天的主题:利用Hash算法实现Hash表
514 1
|
数据安全/隐私保护 Python
散列函数(Hash Function)
散列函数(Hash Function)是一种将任意大小的数据映射到固定大小的数据的函数。通常,散列函数将输入数据转换成固定长度的输出,称为散列值(Hash Value),散列值通常是一串数字和字母组成的固定长度的字符串。散列函数可以用于数据加密、数据完整性检查、数据压缩等方面。
173 1
|
存储 算法
|
存储 算法
hash
一.什么是hash 百度百科上的定义是: 是把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
111 0
|
前端开发 JavaScript
hash、chunkhash和contenthash
webpack 通用配置优化
135 0
hash、chunkhash和contenthash
|
存储 算法 数据安全/隐私保护
Hash 的定义
Hash,一般翻译做散列、杂凑,或音译为哈希。
162 0
|
存储 NoSQL Redis

热门文章

最新文章