MurmurHash PK CityHash

 

MurmurHash PK CityHash

标签: 算法测试alignmentgooglenull语言
  14636人阅读  评论(2)  收藏  举报
  分类:
 
c/c++(25)    Program(21) 
1. 概述
murmurhash是 Austin Appleby于2008年创立的一种 非加密hash算法,适用于基于hash进行查找的场景。murmurhash最新版本是MurMurHash3,支持 32位、64位及128位值的产生。
murmurhash标准使用c++实现,但是也有其他主流语言的支持版本,包括:perl、c#、ruby、python、java等。murmurhash在多个开源项目中得到应用,包括libstdc、libmemcached 、nginx、hadoop等。

CityHash是Google发布的字符串散列算法,和murmurhash一样,属于非加密型hash算法。CityHash算法的开发是受到了 MurmurHash的启发。其主要优点是大部分步骤包含了至少两步独立的数学运算。现代 CPU 通常能从这种代码获得最佳性能。
CityHash 也有其缺点:代码较同类流行算法复杂。 Google 希望为速度而不是为了简单而优化,因此没有照顾较短输入的特例
Google 号称CityHash64 在速度方面至少能提高 30%(这个,肯定不是和murmurhash比咯),并有望提高多达两倍。此外,这些算法的统计特性也很完备。
目前CityHash支持 64、128、256

2.使用:
1)Murmurhash直接添加源码:
[cpp]  view plain  copy
  1. //-----------------------------------------------------------------------------  
  2. // MurmurHash2, 64-bit versions, by Austin Appleby  
  3.   
  4. // The same caveats as 32-bit MurmurHash2 apply here - beware of alignment   
  5. // and endian-ness issues if used across multiple platforms.  
  6.   
  7. typedef unsigned long int uint64_t;  
  8.   
  9. // 64-bit hash for 64-bit platforms  
  10. uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed )  
  11. {  
  12.         const uint64_t m = 0xc6a4a7935bd1e995;  
  13.         const int r = 47;  
  14.   
  15.         uint64_t h = seed ^ (len * m);  
  16.   
  17.         const uint64_t * data = (const uint64_t *)key;  
  18.         const uint64_t * end = data + (len/8);  
  19.   
  20.         while(data != end)  
  21.         {  
  22.                 uint64_t k = *data++;  
  23.   
  24.                 k *= m;   
  25.                 k ^= k >> r;   
  26.                 k *= m;   
  27.   
  28.                 h ^= k;  
  29.                 h *= m;   
  30.         }  
  31.   
  32.         const unsigned char * data2 = (const unsigned char*)data;  
  33.   
  34.         switch(len & 7)  
  35.         {  
  36.         case 7: h ^= uint64_t(data2[6]) << 48;  
  37.         case 6: h ^= uint64_t(data2[5]) << 40;  
  38.         case 5: h ^= uint64_t(data2[4]) << 32;  
  39.         case 4: h ^= uint64_t(data2[3]) << 24;  
  40.         case 3: h ^= uint64_t(data2[2]) << 16;  
  41.         case 2: h ^= uint64_t(data2[1]) << 8;  
  42.         case 1: h ^= uint64_t(data2[0]);  
  43.                 h *= m;  
  44.         };  
  45.    
  46.         h ^= h >> r;  
  47.         h *= m;  
  48.         h ^= h >> r;  
  49.   
  50.         return h;  
  51. }   
  52.   
  53.   
  54. // 64-bit hash for 32-bit platforms  
  55. uint64_t MurmurHash64B ( const void * key, int len, unsigned int seed )  
  56. {  
  57.         const unsigned int m = 0x5bd1e995;  
  58.         const int r = 24;  
  59.   
  60.         unsigned int h1 = seed ^ len;  
  61.         unsigned int h2 = 0;  
  62.   
  63.         const unsigned int * data = (const unsigned int *)key;  
  64.   
  65.         while(len >= 8)  
  66.         {  
  67.                 unsigned int k1 = *data++;  
  68.                 k1 *= m; k1 ^= k1 >> r; k1 *= m;  
  69.                 h1 *= m; h1 ^= k1;  
  70.                 len -= 4;  
  71.   
  72.                 unsigned int k2 = *data++;  
  73.                 k2 *= m; k2 ^= k2 >> r; k2 *= m;  
  74.                 h2 *= m; h2 ^= k2;  
  75.                 len -= 4;  
  76.         }  
  77.   
  78.         if(len >= 4)  
  79.         {  
  80.                 unsigned int k1 = *data++;  
  81.                 k1 *= m; k1 ^= k1 >> r; k1 *= m;  
  82.                 h1 *= m; h1 ^= k1;  
  83.                 len -= 4;  
  84.         }  
  85.   
  86.         switch(len)  
  87.         {  
  88.         case 3: h2 ^= ((unsigned char*)data)[2] << 16;  
  89.         case 2: h2 ^= ((unsigned char*)data)[1] << 8;  
  90.         case 1: h2 ^= ((unsigned char*)data)[0];  
  91.                         h2 *= m;  
  92.         };  
  93.   
  94.         h1 ^= h2 >> 18; h1 *= m;  
  95.         h2 ^= h1 >> 22; h2 *= m;  
  96.         h1 ^= h2 >> 17; h1 *= m;  
  97.         h2 ^= h1 >> 19; h2 *= m;  
  98.   
  99.         uint64_t h = h1;  
  100.   
  101.         h = (h << 32) | h2;  
  102.   
  103.         return h;  
  104. }   
2)cityhash需要下载、配置、编译后才能使用

3.测试代码:
[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <string>  
  3. #include <time.h>  
  4. #include "city.h"  
  5. using namespace std;  
  6.   
  7. uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed );  
  8.   
  9. int main(int argc, char** argv)  
  10. {  
  11.   
  12.         char buf[1024];  
  13.         time_t t1, t2;  
  14.         FILE* file = fopen(argv[1], "r");  
  15.         int pattern = atoi(argv[2]);  
  16.   
  17.         t1 = time(NULL);  
  18.         while(fgets(buf, 1024, file) != NULL)  
  19.         {  
  20.                 if(1 == pattern)  
  21.                 {  
  22.                         MurmurHash64A(buf, strlen(buf), 16);  
  23.                 }  
  24.                 else  
  25.                 {  
  26.                         CityHash64WithSeed(buf, strlen(buf), 16);  
  27.                 }  
  28.         }  
  29.         t2 = time(NULL);  
  30.   
  31.         cout << (t2-t1) << endl;  
  32.         return 0;  
  33. }  

生成随机字符串bash脚本:
[cpp]  view plain  copy
  1. #!/bin/sh  
  2. #sh make_random_strings 16 10000  
  3. #make 10000 strings, the string length:16  
  4.   
  5. for((j=0; j<$2; j++))  
  6. {  
  7.         str=  
  8.         for((i=0; i<$1; i++))  
  9.         {  
  10.                 one=`cat /dev/urandom |strings -n 1 | cut -c-1| head -1`  
  11.                 str=${str}${one}  
  12.         }  
  13.   
  14.         echo $str  
  15. }  


测试长度16的字符串hash速度

测试数据:
735,529,084行 长度16的随机字符串
murmurhash平均耗时:94s
cityhash平均耗时:86s

测试长度 32的字符串hash速度
测试数据:
262,017,242行 长度32的随机字符串
murmurhash平均耗时:33
cityhash平均耗时:33

测试长度 256的字符串hash速度
测试数据:
60,000,000行 长度256的随机字符串
murmurhash平均耗时:32
cityhash平均耗时:30

4.总结:

速度: cityhash和murmurhash相比,速度略快
使用复杂度:都非常简单
语言支持:murmurhash主流语言基本都支持;cityhash 2010才发布算法,2011年发布实现,目前只有c++的支持。
hash值位数:murmurhash支持32、64、128bit, cityhash支持64、128、256bit


reference:
http://code.google.com/p/cityhash/
wiki:http://en.wikipedia.org/wiki/CityHash
wiki:http://en.wikipedia.org/wiki/Murmurhash

你可能感兴趣的:(算法,Google,测试,null,语言,alignment)