WebKit性能的基石 ----- Hash 函数介绍

http://blog.csdn.net/onecoolx/article/details/9453359
      WebKit 内核的浏览器一直以性能优异而著称。优异的性能来源于底层巧妙的设计与实现。这篇文章简要的介绍一下WebKit性能的基石 ----- Hash函数。

Webkit内核源代码中包含一套全新实现的基础模板库 ---- WTF。 WTF提供了基本的容器类 如:Vector, Deque, HaspMap, AVLTree 等,还提供了如智能指针,定时器,线程,消息队列,内存池等实现。这些基础代码使WebKit可以不依赖任何第三方C++类库如 STL, Boost 等,从而提供最大限度的可移植性。   WTF中的HashMap是WebKit中使用最多也是操作最为频繁的容器,它的性能直接影响WebKit的整体性能,所以hash函数的实现显得尤为重要。

    WTF中的Hash函数主要是两类,一类是整数Hash算法,包括 8bit,16bit,32bit,64bit。指针类型按位数转换成相应的整数进行运算,浮点类型也按所占字节数数转换成相应的整数进行Hash运算,如32位系统中 float 类型按 32bit整数运算, double类型按64bit整数计算Hash值。另一类就是使用最多的字符串Hash算法,包括8bit (char) 和16bit(unicode)两种。

    整数的Hash算法使用的是Thomas Wang's 32 Bit / 64 Bit Mix Function ,这是一种基于位移运算的散列方法。基于移位的散列是使用Key值进行移位操作。通常是结合左移和右移。每个移位过程的结果进行累加,最后移位的结果作为最终结果。这种方法的好处是避免了乘法运算,从而提高Hash函数本身的性能。下面来看看 32bit整数的Hash函数实现:

[cpp]  view plain  copy
  1. unsigned intHash(uint32_t key)  
  2. {  
  3.         key += ~(key << 15);  
  4.         key ^= (key >> 10);  
  5.         key += (key << 3);  
  6.         key ^= (key >> 6);  
  7.         key += ~(key << 11);  
  8.         key ^= (key >> 16);  
  9.         return key;  
  10. }  


64bit 整数的版本同32bit类似,只是计算位数更多:

 

[cpp]  view plain  copy
  1. unsigned intHash(uint64_t key)  
  2. {  
  3.         key += ~(key << 32);  
  4.         key ^= (key >> 22);  
  5.         key += ~(key << 13);  
  6.         key ^= (key >> 8);  
  7.         key += (key << 3);  
  8.         key ^= (key >> 15);  
  9.         key += ~(key << 27);  
  10.         key ^= (key >> 31);  
  11.         return static_cast<unsigned>(key);  
  12. }  

 

    字符串的Hash算法是WebKit中最重要的算法,它来自于Paul Hsieh's SuperFastHash算法。http://www.azillionmonkeys.com/qed/hash.html

Hash函数的设计原则是使用最小的代价迅速达到雪崩效应(如:输入中1bit的变化 影响 输出中1/4 到 1/2的bits变化)。来看看 Pual Hsieh的实现:

[cpp]  view plain  copy
  1. #include "pstdint.h" /* Replace with <stdint.h> if appropriate */  
  2. #undef get16bits  
  3. #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \  
  4.   || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)  
  5. #define get16bits(d) (*((const uint16_t *) (d)))  
  6. #endif  
  7.   
  8. #if !defined (get16bits)  
  9. #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\  
  10.                        +(uint32_t)(((const uint8_t *)(d))[0]) )  
  11. #endif  
  12.   
  13. uint32_t SuperFastHash (const char * data, int len) {  
  14. uint32_t hash = len, tmp;  
  15. int rem;  
  16.   
  17.     if (len <= 0 || data == NULL) return 0;  
  18.   
  19.     rem = len & 3;  
  20.     len >>= 2;  
  21.   
  22.     /* Main loop */  
  23.     for (;len > 0; len--) {  
  24.         hash  += get16bits (data);  
  25.         tmp    = (get16bits (data+2) << 11) ^ hash;  
  26.         hash   = (hash << 16) ^ tmp;  
  27.         data  += 2*sizeof (uint16_t);  
  28.         hash  += hash >> 11;  
  29.     }  
  30.   
  31.     /* Handle end cases */  
  32.     switch (rem) {  
  33.         case 3: hash += get16bits (data);  
  34.                 hash ^= hash << 16;  
  35.                 hash ^= ((signed char)data[sizeof (uint16_t)]) << 18;  
  36.                 hash += hash >> 11;  
  37.                 break;  
  38.         case 2: hash += get16bits (data);  
  39.                 hash ^= hash << 11;  
  40.                 hash += hash >> 17;  
  41.                 break;  
  42.         case 1: hash += (signed char)*data;  
  43.                 hash ^= hash << 10;  
  44.                 hash += hash >> 1;  
  45.     }  
  46.   
  47.     /* Force "avalanching" of final 127 bits */  
  48.     hash ^= hash << 3;  
  49.     hash += hash >> 5;  
  50.     hash ^= hash << 4;  
  51.     hash += hash >> 17;  
  52.     hash ^= hash << 25;  
  53.     hash += hash >> 6;  
  54.   
  55.     return hash;  
  56. }  

经过Benckmark的测试, 这种实现方法在主流平台比现有的其它Hash函数都要快很多。

 
AMD Athlon XP 1.620Ghz
Power4 1Ghz
UltraSparc
III 1.2Ghz
 Intel C/C++
/O2 /G6 /Qaxi /Qxi /Qip
MSVC
/O2 /Ot /Og /G6
WATCOM C/C++
/otexan /6r
GCC
-O3 -march=athlon-xp
GCC
-O3 -mpowerpc64
CC 32bit
-O
CRC326.425.665.665.6714.068.75
One at a Time5.765.665.665.6912.795.57
Alpha Numeric3.294.064.065.6710.265.52
FNV Hash4.884.844.834.878.9211.98
Bob Jenkins2.082.362.032.076.163.08
SuperFastHash1.541.921.591.343.712.15

Data is time in seconds taken to hash a random buffer of 256 bytes 5 million times.Download test here

 

        结束语,WebKit性能很高来源于很多设计的非常优秀的算法和开源软件实现,Hash函数只是其中的一个方面。但正是由于字符串Hash函数性能很高,基于它实现的String类和AtomicString类等基础代码才能获得极高的性能。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值