之前寫PHP的時候,哈希函數就只用過md5和sha1,也是最經常使用的兩個。如今多數用python,又據說twitter用的是FNV,因而就用上了。 python
FNV產生的是一個整數,32位或者64位或者更多。通常用來作字符串哈希的話,須要64位。32位的碰撞率咱不放心。整數的結果,比起md5和sha1的字符串結果,存儲空間要小一點。並且FNV也是比較快的。 svn
現成的FNV的python模塊是pyfasthash。這個項目名字叫pyfasthash,但模塊名字叫pyhash。並且直接經過easy_install是安裝不了的,在Downloads那裏下載的解壓出來也是安裝不了的。要checkout svn裏面的源碼才能夠。當初就是搗鼓一個晚上才發現。並且它依賴c++的boost庫,編譯時間很漫長。總之吐槽點不少。不過用起來還算順手。 函數
今晚看到了這個:http://sites.google.com/site/murmurhash/avalanche。看上去FNV很不濟 -_,-。因而就試下里面最好的murmur。這個頁面正是murmur的做者作的。官網在:http://sites.google.com/site/murmurhash/。雖然也有另一個現成的murmur的python模塊(地址),可是是隻有32bit的沒有64bit的。32bit的不夠用。因而只好把它64bit的源碼下回來本身封裝。代碼很少: ui
#include "Python.h" unsigned long long MurmurHash64B ( const void * key, int len, unsigned int seed ) { const unsigned int m = 0x5bd1e995; const int r = 24; unsigned int h1 = seed ^ len; unsigned int h2 = 0; const unsigned int * data = (const unsigned int *)key; while(len >= 8) { unsigned int k1 = *data++; k1 *= m; k1 ^= k1 >> r; k1 *= m; h1 *= m; h1 ^= k1; len -= 4; unsigned int k2 = *data++; k2 *= m; k2 ^= k2 >> r; k2 *= m; h2 *= m; h2 ^= k2; len -= 4; } if(len >= 4) { unsigned int k1 = *data++; k1 *= m; k1 ^= k1 >> r; k1 *= m; h1 *= m; h1 ^= k1; len -= 4; } switch(len) { case 3: h2 ^= ((unsigned char*)data)[2] << 16; case 2: h2 ^= ((unsigned char*)data)[1] << 8; case 1: h2 ^= ((unsigned char*)data)[0]; h2 *= m; }; h1 ^= h2 >> 18; h1 *= m; h2 ^= h1 >> 22; h2 *= m; h1 ^= h2 >> 17; h1 *= m; h2 ^= h1 >> 19; h2 *= m; unsigned long long h = h1; h = (h << 32) | h2; return h; } static PyObject * hash(PyObject *self, PyObject *args) { const char *p; PyArg_ParseTuple(args, "s", &p); unsigned long long ret = MurmurHash64B(p, strlen(p), 0x19870714); return PyLong_FromUnsignedLongLong(ret); } static PyMethodDef PythonPymurmurModules[] = { {"hash", hash, METH_VARARGS, "64bit murmur hash function"}, {NULL, NULL, 0, NULL} }; PyMODINIT_FUNC initpymurmur(void) { Py_InitModule("pymurmur", PythonPymurmurModules); }
主要函數都是照搬的(看代碼風格就知道 -_,-),只是改了下數據類型。uint64_t改爲unsigned long long。distutils編譯安裝完畢。 google
100w個整數轉字符串再hash的結果,FNV耗時5s+,murmur耗時1s+,快得很明顯。
再隨機生成長128的字符串,hash了220w+次,沒有發現碰撞(跑了半個小時,沒耐心了)。
不錯用! spa