eina: add murmur3 hash

SVN revision: 65017
This commit is contained in:
Boris Faure 2011-11-10 10:58:19 +00:00
parent c049c0e12b
commit 37efd502fe
3 changed files with 114 additions and 2 deletions

View File

@ -1020,7 +1020,9 @@ static inline int eina_hash_int32(const unsigned int *pkey,
int len) EINA_ARG_NONNULL(1);
static inline int eina_hash_int64(const unsigned long int *pkey,
int len) EINA_ARG_NONNULL(1);
/* http://sites.google.com/site/murmurhash/ */
static inline int eina_hash_murmur3(const char *key,
int len) EINA_ARG_NONNULL(1);
#include "eina_inline_hash.x"
/**

View File

@ -85,4 +85,67 @@ eina_hash_int64(const unsigned long int *pkey, int len)
return (int) key;
}
static inline unsigned int _rotl32(unsigned int x, char r)
{
return (x << r) | (x >> (32 - r));
}
static inline unsigned int _fmix32(unsigned int h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
int
eina_hash_murmur3(const char *key, int len)
{
const unsigned char * data = (const unsigned char*)key;
const int nblocks = len / 4;
unsigned int h1 = 0, k1;
unsigned int c1 = 0xcc9e2d51;
unsigned int c2 = 0x1b873593;
const unsigned int * blocks = (const unsigned int *)(data + nblocks*4);
int i;
const unsigned char *tail;
for(i = -nblocks; i; i++)
{
k1 = blocks[i];
k1 *= c1;
k1 = _rotl32(k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = _rotl32(h1, 13);
h1 = h1*5+0xe6546b64;
}
tail = (const unsigned char*)(data + nblocks*4);
k1 = 0;
switch(len & 3)
{
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = _rotl32(k1, 16);
k1 *= c2;
h1 ^= k1;
}
h1 ^= len;
return _fmix32(h1);
}
#endif

View File

@ -144,6 +144,49 @@ eina_bench_lookup_rbtree(int request)
eina_rbtree_delete(root, EINA_RBTREE_FREE_CB(_eina_bench_rbtree_free), NULL);
}
static void
eina_bench_lookup_murmur(int request)
{
Eina_Hash *hash = NULL;
int *tmp_val;
unsigned int i;
unsigned int j;
hash = eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
EINA_KEY_CMP(_eina_string_key_cmp),
EINA_KEY_HASH(eina_hash_murmur3),
free,
8);
for (i = 0; i < (unsigned int)request; ++i)
{
char tmp_key[10];
tmp_val = malloc(sizeof (int));
if (!tmp_val)
continue;
eina_convert_itoa(i, tmp_key);
*tmp_val = i;
eina_hash_add(hash, tmp_key, tmp_val);
}
srand(time(NULL));
for (j = 0; j < 200; ++j)
for (i = 0; i < (unsigned int)request; ++i)
{
char tmp_key[10];
eina_convert_itoa(rand() % request, tmp_key);
tmp_val = eina_hash_find(hash, tmp_key);
}
eina_hash_free(hash);
}
#ifdef CITYHASH_BENCH
static void
eina_bench_lookup_cityhash(int request)
@ -476,10 +519,13 @@ void eina_bench_hash(Eina_Benchmark *bench)
eina_benchmark_register(bench, "djb2-lookup-inline",
EINA_BENCHMARK(
eina_bench_lookup_djb2_inline), 10, 10000, 10);
eina_benchmark_register(bench, "murmur",
EINA_BENCHMARK(
eina_bench_lookup_murmur), 10, 10000, 10);
#ifdef CITYHASH_BENCH
eina_benchmark_register(bench, "cityhash",
EINA_BENCHMARK(
eina_bench_lookup_cityhash), 10, 10000, 10);
eina_bench_lookup_cityhash), 10, 10000, 10);
#endif
eina_benchmark_register(bench, "rbtree",
EINA_BENCHMARK(
@ -495,4 +541,5 @@ void eina_bench_hash(Eina_Benchmark *bench)
eina_benchmark_register(bench, "ecore-lookup",
EINA_BENCHMARK(
eina_bench_lookup_ecore), 10, 10000, 10);
}