Skip to content

Commit 334173f

Browse files
committed
Use FNV1a hash instead of Murmur3
It's much simpler, and in some cases can even be inlined.
1 parent 71dbc35 commit 334173f

File tree

7 files changed

+46
-393
lines changed

7 files changed

+46
-393
lines changed

src/bin/tools/CMakeLists.txt

-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ else ()
55
add_executable(mimegen
66
mimegen.c
77
${CMAKE_SOURCE_DIR}/src/lib/hash.c
8-
${CMAKE_SOURCE_DIR}/src/lib/murmur3.c
98
${CMAKE_SOURCE_DIR}/src/lib/missing.c
109
)
1110
if (LWAN_HAVE_BROTLI)
@@ -37,7 +36,6 @@ else ()
3736
${CMAKE_SOURCE_DIR}/src/lib/lwan-strbuf.c
3837
${CMAKE_SOURCE_DIR}/src/lib/missing.c
3938
${CMAKE_SOURCE_DIR}/src/lib/hash.c
40-
${CMAKE_SOURCE_DIR}/src/lib/murmur3.c
4139
)
4240

4341
add_executable(weighttp weighttp.c)

src/lib/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ set(SOURCES
3939
missing.c
4040
missing-pthread.c
4141
missing-epoll.c
42-
murmur3.c
4342
patterns.c
4443
realpathat.c
4544
sd-daemon.c

src/lib/hash.c

+15-17
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434

3535
#include "lwan-private.h"
3636
#include "hash.h"
37-
#include "murmur3.h"
3837

3938
struct hash_bucket {
4039
void **keys;
@@ -81,11 +80,12 @@ struct hash_entry {
8180
static_assert((MIN_BUCKETS & (MIN_BUCKETS - 1)) == 0,
8281
"Bucket size is power of 2");
8382

83+
static inline unsigned int hash_fnv1a_32(const void *keyptr);
8484
static inline unsigned int hash_int_shift_mult(const void *keyptr);
8585
static inline unsigned int hash_int64_shift_mult(const void *keyptr);
8686

8787
static unsigned int odd_constant = DEFAULT_ODD_CONSTANT;
88-
static unsigned (*hash_str)(const void *key) = murmur3_simple;
88+
static unsigned (*hash_str)(const void *key) = hash_fnv1a_32;
8989
static unsigned (*hash_int)(const void *key) = hash_int_shift_mult;
9090
static unsigned (*hash_int64)(const void *key) = hash_int64_shift_mult;
9191

@@ -115,28 +115,21 @@ static bool resize_bucket(struct hash_bucket *bucket, unsigned int new_size)
115115
return false;
116116
}
117117

118+
static inline unsigned int hash_fnv1a_32(const void *keyptr)
119+
{
120+
return fnv1a_32(keyptr, strlen(keyptr));
121+
}
122+
118123
static inline unsigned int hash_int_shift_mult(const void *keyptr)
119124
{
120-
/* http://www.concentric.net/~Ttwang/tech/inthash.htm */
121125
unsigned int key = (unsigned int)(long)keyptr;
122-
unsigned int c2 = odd_constant;
123-
124-
key = (key ^ 61) ^ (key >> 16);
125-
key += key << 3;
126-
key ^= key >> 4;
127-
key *= c2;
128-
key ^= key >> 15;
129-
return key;
126+
return fnv1a_32(&key, sizeof(key));
130127
}
131128

132129
static inline unsigned int hash_int64_shift_mult(const void *keyptr)
133130
{
134131
const uint64_t key = (uint64_t)(uintptr_t)keyptr;
135-
uint32_t key_low = (uint32_t)(key & 0xffffffff);
136-
uint32_t key_high = (uint32_t)(key >> 32);
137-
138-
return hash_int_shift_mult((void *)(uintptr_t)key_low) ^
139-
hash_int_shift_mult((void *)(uintptr_t)key_high);
132+
return fnv1a_32(&key, sizeof(key));
140133
}
141134

142135
#if defined(LWAN_HAVE_BUILTIN_CPU_INIT) && defined(LWAN_HAVE_BUILTIN_IA32_CRC32)
@@ -200,14 +193,19 @@ static inline unsigned int hash_int64_crc32(const void *keyptr)
200193

201194
#endif
202195

196+
uint64_t fnv1a_64_seed = 0xcbf29ce484222325ull;
197+
uint32_t fnv1a_32_seed = 0x811c9dc5u;
198+
203199
__attribute__((constructor(65535))) static void initialize_odd_constant(void)
204200
{
205201
/* This constant is randomized in order to mitigate the DDoS attack
206202
* described by Crosby and Wallach in UsenixSec2003. */
207203
if (lwan_getentropy(&odd_constant, sizeof(odd_constant), 0) < 0)
208204
odd_constant = DEFAULT_ODD_CONSTANT;
209205
odd_constant |= 1;
210-
murmur3_set_seed(odd_constant);
206+
207+
fnv1a_64_seed = fnv1a_64(&odd_constant, sizeof(odd_constant));
208+
fnv1a_32_seed = fnv1a_32(&odd_constant, sizeof(odd_constant));
211209

212210
#if defined(LWAN_HAVE_BUILTIN_CPU_INIT) && defined(LWAN_HAVE_BUILTIN_IA32_CRC32)
213211
__builtin_cpu_init();

src/lib/hash.h

+28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <stdint.h>
34
#include <stdbool.h>
45
#include <sys/types.h>
56

@@ -30,3 +31,30 @@ void hash_iter_init(const struct hash *hash, struct hash_iter *iter);
3031
bool hash_iter_next(struct hash_iter *iter,
3132
const void **key,
3233
const void **value);
34+
35+
extern uint64_t fnv1a_64_seed;
36+
extern uint32_t fnv1a_32_seed;
37+
38+
static inline uint64_t fnv1a_64(const void *buffer, size_t len)
39+
{
40+
const unsigned char *data = (unsigned char *)buffer;
41+
uint64_t hash;
42+
43+
for (hash = fnv1a_64_seed; len--; data++) {
44+
hash = (hash ^ *data) * 0x100000001b3ul;
45+
}
46+
47+
return hash;
48+
}
49+
50+
static inline uint32_t fnv1a_32(const void *buffer, size_t len)
51+
{
52+
const unsigned char *data = (unsigned char *)buffer;
53+
uint32_t hash;
54+
55+
for (hash = fnv1a_32_seed; len--; data++) {
56+
hash = (hash ^ *data) * 0x1000193u;
57+
}
58+
59+
return hash;
60+
}

src/lib/lwan-thread.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
#endif
4848

4949
#include "list.h"
50-
#include "murmur3.h"
5150
#include "lwan-private.h"
5251
#include "lwan-tq.h"
5352

@@ -124,9 +123,10 @@ static void lwan_random_seed_prng_for_thread(const struct lwan_thread *t)
124123
{
125124
if (lwan_getentropy(&lehmer64_state, sizeof(lehmer64_state), 0) < 0) {
126125
lwan_status_warning("Couldn't get proper entropy for PRNG, using fallback seed");
127-
lehmer64_state |= murmur3_fmix64((uint64_t)(uintptr_t)t);
126+
uintptr_t ptr = (uintptr_t)t;
127+
lehmer64_state |= fnv1a_64(&ptr, sizeof(ptr));
128128
lehmer64_state <<= 64;
129-
lehmer64_state |= murmur3_fmix64((uint64_t)t->epoll_fd);
129+
lehmer64_state |= fnv1a_64(&t->epoll_fd, sizeof(t->epoll_fd));
130130
}
131131
}
132132

0 commit comments

Comments
 (0)