DJBX33A(time33 hash)实现原理

原文地址:http://www.cnblogs.com/napoleon_liu/articles/1911571.html


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(); //1 
            TIME33_HASH_MIXED_CH(); //2 
            TIME33_HASH_MIXED_CH(); //3 
            TIME33_HASH_MIXED_CH(); //4 
            TIME33_HASH_MIXED_CH(); //5 
            TIME33_HASH_MIXED_CH(); //6 
            TIME33_HASH_MIXED_CH(); //7 
            TIME33_HASH_MIXED_CH(); //8 
       } 
       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.


### 回答1: fm33a0610是一款多功能射频集成电路芯片,具有广泛的应用领域。封装原理图是指将芯片的管脚与外部电路进行连接的电路设计图纸。 fm33a0610芯片的封装原理图具体包含以下几个主要部分: 1. 电源与功率管理部分:封装原理图中会设计芯片的电源供应电路以及功率管理电路,包括稳压电路、滤波电路等,以确保芯片正常工作的电源条件和电源稳定性。 2. 射频收发器件部分:该芯片作为射频集成电路,其封装原理图中会包含射频前端的收发器件部分。该部分设计涵盖了射频输入输出端口的滤波器、放大器、混频器、振荡器等电路,以实现射频信号的收发功能。 3. 控制与数字处理部分:该芯片还包含控制与数字处理电路,封装原理图中会设计与控制芯片通信的接口电路以及时钟电路等。该部分电路负责芯片的控制逻辑和信号处理功能。 4. 外设接口部分:fm33a0610芯片支持与外部外设连接,封装原理图中会设计供外设连接的接口电路,例如UART、SPI、I2C等通信接口,以实现与外设的数据交互。 总之,fm33a0610芯片的封装原理图涵盖了电源与功率管理、射频收发器件、控制与数字处理以及外设接口等多个部分,其设计目的是将芯片与外部电路进行正确连接,确保芯片正常工作,并为芯片的各项功能提供良好的支持和协同工作的条件。 ### 回答2: fm33a0610是一款多功能芯片,其原理图封装主要指的是对该芯片的原理图进行合理封装和设计。 原理图是电子产品设计过程中的关键一步,它是将芯片内部功能以电路图的形式呈现出来。fm33a0610的原理图封装主要包括以下几个方面: 1. 引脚配置:原理图封装需要准确配置每个引脚的作用和功能。根据fm33a0610芯片的技术规格和需求,为每个引脚分配正确的功能,例如电源输入、信号输入输出、通信接口等。 2. 电路连接:原理图封装需要将芯片内部的各个功能模块按照正确的电路连接方式进行布局。根据芯片的内部结构和电路信号传输的要求,进行电路连接的规划和设计,确保信号的准确传输和功能的正常运行。 3. 外围电路:fm33a0610芯片的原理图封装还需要考虑外围电路的设计。这包括电源电路、时钟电路、复位电路等。这些外围电路的设计对芯片的正常工作、稳定性和可靠性起到重要作用。 4. 信号调整和滤波:在原理图封装过程中,还需要对芯片的输入输出信号进行调整和滤波。通过添加合适的电阻、电容和滤波器等元件,对输入信号进行处理和滤波,以使输出信号更加稳定和可靠。 综上所述,fm33a0610的原理图封装是对该芯片的功能、引脚、电路连接和外围电路等进行合理设计和封装的过程。这一过程是确保该芯片正常工作和性能稳定的重要环节,需要根据技术规格和产品需求进行精确规划和设计。 ### 回答3: fm33a0610是一款集成电路芯片,其原理图封装主要涉及到芯片内部电路设计和布局。原理图封装是指将芯片内部各个部件的连接方式以图形的形式展示出来,方便电路设计和布局的工作。 首先,在fm33a0610的原理图封装中会包括芯片内部的各个功能模块,如中央处理器、存储器、输入输出接口等。这些功能模块在原理图中会以符号的形式表示,并通过连线来表示它们之间的连接关系。 其次,在fm33a0610的原理图封装中还会包括芯片的电源电路和引脚连接。电源电路是保证芯片正常工作所必需的,其连接方式会在原理图中明确标记出来。引脚连接则表示芯片与外部器件之间的信号传输和控制关系,通过引脚连接可以实现芯片与外部电路的交互。 此外,在fm33a0610的原理图封装中还会涉及到一些电路保护和滤波电路的设计。电路保护是为了保护芯片免受过电流、过热、过压等异常情况的损害,滤波电路则用于去除输入输出信号中的噪声和杂散。 总之,fm33a0610原理图封装是将芯片内部电路设计和布局以图形的形式展示出来,方便电路设计和布局的工作。通过原理图封装,可以清晰地了解芯片的功能模块、电源电路、引脚连接以及电路保护和滤波等细节,为芯片的应用提供了基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值