在Web服务器lighttpd里,使用的是一个非常流行的DJB hash function,即俗称“Times33”的哈希算法,这个算法很简单,就是不断的乘33。
看实际代码:
|
初始值为什么是5381?看这里:http://stackoverflow.com/questions/10696223/reason-for-5381-number-in-djb-hash-function
结构体buffer的定义如下:
|
typedef struct {
char *ptr;
size_t used;
size_t size;
} buffer;
因此,可以看到函数hashme()就是将一个字符串哈希成一个整型值,在很多场景下都有这种需求,比如Hash Map,其key值为字符串(以方便人看懂),而内部实际使用的是整型值(以方便机器操作),在lighttpd这里也是这样,它需要把一个文件路径名转换为一个整型哈希值。
对于一个哈希函数,我们总是期望它有更少的冲突,怎样判断一个哈希函数在冲突方面的好坏,貌似有一个名为avalanche test(雪崩测试)的密码学概念,关于它的具体含义,我暂且也不甚了了,但在nginx的1.0.1里用到了一个名为MurmurHash2算法,据说它有更少的冲突,代码如下:
uint32_t
ngx_murmur_hash2(u_char *data, size_t len)
{
uint32_t h, k;
h = 0 ^ len;
while (len >= 4) {
k = data[0];
k |= data[1] << 8;
k |= data[2] << 16;
k |= data[3] << 24;
k *= 0x5bd1e995;
k ^= k >> 24;
k *= 0x5bd1e995;
h *= 0x5bd1e995;
h ^= k;
data += 4;
len -= 4;
}
switch (len) {
case 3:
h ^= data[2] << 16;
case 2:
h ^= data[1] << 8;
case 1:
h ^= data[0];
h *= 0x5bd1e995;
}
h ^= h >> 13;
h *= 0x5bd1e995;
h ^= h >> 15;
return h;
这个,逻辑真心有点复杂,而且现在已有更进一步的改进版MurmurHash3,嘛,算了,不管它,呵呵。在这里:https://sites.google.com/site/murmurhash/avalanche可以看到一些哈希函数的雪崩测试结果。
转自:http://www.lenky.info/archives/2012/12/2150