From 37efd502fe75883ebb03520ff8761787167343d8 Mon Sep 17 00:00:00 2001 From: Boris Faure Date: Thu, 10 Nov 2011 10:58:19 +0000 Subject: [PATCH] eina: add murmur3 hash SVN revision: 65017 --- legacy/eina/src/include/eina_hash.h | 4 +- legacy/eina/src/include/eina_inline_hash.x | 63 ++++++++++++++++++++++ legacy/eina/src/tests/eina_bench_hash.c | 49 ++++++++++++++++- 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/legacy/eina/src/include/eina_hash.h b/legacy/eina/src/include/eina_hash.h index 71de90ba23..c8eb04861b 100644 --- a/legacy/eina/src/include/eina_hash.h +++ b/legacy/eina/src/include/eina_hash.h @@ -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" /** diff --git a/legacy/eina/src/include/eina_inline_hash.x b/legacy/eina/src/include/eina_inline_hash.x index 0fb992b620..f27060fb3d 100644 --- a/legacy/eina/src/include/eina_inline_hash.x +++ b/legacy/eina/src/include/eina_inline_hash.x @@ -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 diff --git a/legacy/eina/src/tests/eina_bench_hash.c b/legacy/eina/src/tests/eina_bench_hash.c index 46feedc0a8..5b42318eb2 100644 --- a/legacy/eina/src/tests/eina_bench_hash.c +++ b/legacy/eina/src/tests/eina_bench_hash.c @@ -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); + }