python的fnv哈希扩展

自己写一个python的fnv哈希的扩展,文件名fnv_module.c

#include <Python.h> #include <sys/types.h> /* typedef unsigned long fnv_t; */ typedef u_int32_t fnv_t; static fnv_t FNVHash(char* data, size_t n) { unsigned char *s = (unsigned char*)data; fnv_t hash = 2166136261UL; while(*s) { hash *= 16777619; hash %= 0xFFFFFFFF; hash ^= (fnv_t)*s++; } return hash; } PyObject* fnvhash(PyObject *self, PyObject *args) { int hash; char *s; PyObject* pInt; if(!PyArg_ParseTuple(args, "s", &s)) return NULL; hash = FNVHash(s, strlen(s)); /* pInt = Py_BuildValue("i", hash); */ pInt = PyLong_FromUnsignedLong(hash); return pInt; } static PyMethodDef fnv_hash_methods[] = { {"fnvhash", fnvhash, METH_VARARGS, "Caculate FNV-32 hash!"}, {NULL, NULL} }; void initfnv() { PyObject* m; m = Py_InitModule("fnv", fnv_hash_methods); }  

 

编译

gcc -o fnv.so -I /usr/include/python2.6 -shared -fpic fnv_module.c 

 

调用方法

i = 0 import fnv while i < 500000 : fnv.fnvhash('http://s.goso.cn/s?keyword=%d' % i) i += 1  

测试了一下速度,50万次hash计算

time python ./fnv_test.py real 0m1.589s user 0m1.500s sys 0m0.036s 

平均3微秒一次,速度还算可以。

 

在fnv_module.c中PyLong_FromUnsignedLong(hash)那行,我原先用的是Py_BuildValue("i", hash)返回的数值老出现负值。

在google上搜一下,找到PyLong_FromUnsignedLong函数,它可以接受一个unsigned类型的整数,返回也是一个unsigned类型整数。

替换之后,完全正确。

 

附:fnv哈希的纯Python实现,只是效率太低,50万次计算hash需要32秒。

是c模块实现的效率的5%不到

#!/usr/bin/env python fnv_prime = 16777619 offset_basis = 2166136261 mask = pow(2, 32) def fnvhash(buff) : hval = offset_basis for s in buff : hval *= fnv_prime hval %= mask hval ^= ord(s) return hval 

 

你可能感兴趣的:(python,Google,null,扩展,import,methods)