did not need to be enabled to be enabled (performance issue).
* Rewrote bounds checking code for get calls.
* "make test" now starts its own memcached servers.
+ * Added Hseih hash (MEMCACHED_HASH_HSIEH), which is showing about 7%
+ performance over standard hash.
0.10 Tue Nov 20 23:22:31 PST 2007
* Added append binary test.
Dustin Sallings - Insight into protocol
Tobias Luetke - Performance Feedback
Andre Cruz - Help with getting the CRC Hash function to match other connectors
+Brian Pontz - Hsieh hash
MEMCACHED_HASH_FNV1_32,
MEMCACHED_HASH_FNV1A_32,
MEMCACHED_HASH_KETAMA,
+ MEMCACHED_HASH_HSIEH,
} memcached_hash;
typedef enum {
lib_LTLIBRARIES = libmemcached.la
libmemcached_la_SOURCES = crc.c \
+ hsieh_hash.c \
memcached.c \
memcached_auto.c \
memcached_behavior.c \
void md5_signature(unsigned char *key, unsigned int length, unsigned char *result);
uint32_t hash_crc32(const char *data,
size_t data_len);
+uint32_t hsieh_hash(char *key, size_t key_length);
memcached_return memcached_connect(memcached_st *ptr, unsigned int server_key);
memcached_return memcached_response(memcached_st *ptr,
--- /dev/null
+/* By Paul Hsieh (C) 2004, 2005. Covered under the Paul Hsieh
+ * derivative license.
+ * See: http://www.azillionmonkeys.com/qed/weblicense.html for license
+ * details.
+ * http://www.azillionmonkeys.com/qed/hash.html
+*/
+
+#include "common.h"
+
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__))
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+ +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+
+uint32_t hsieh_hash(char *key, size_t key_length)
+{
+ uint32_t hash = 0, tmp;
+ int rem;
+
+ if (key_length <= 0 || key == NULL) return 0;
+
+ rem = key_length & 3;
+ key_length >>= 2;
+
+ /* Main loop */
+ for (;key_length > 0; key_length--) {
+ hash += get16bits (key);
+ tmp = (get16bits (key+2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ key += 2*sizeof (uint16_t);
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (rem) {
+ case 3: hash += get16bits (key);
+ hash ^= hash << 16;
+ hash ^= key[sizeof (uint16_t)] << 18;
+ hash += hash >> 11;
+ break;
+ case 2: hash += get16bits (key);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ case 1: hash += *key;
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+}
+
hash= internal_generate_ketama_md5(key, key_length);
break;
}
+ case MEMCACHED_HASH_HSIEH:
+ {
+ hash= hsieh_hash(key, key_length);
+ break;
+ }
}
WATCHPOINT_ASSERT(hash);
}
else if (!memcmp("connection_structures", key, strlen("connection_structures")))
{
- //stat->connection_structures= strtol(value, (char **)NULL, 10);
+ stat->connection_structures= strtol(value, (char **)NULL, 10);
}
else if (!memcmp("cmd_get", key, strlen("cmd_get")))
{
- //stat->cmd_get= strtoll(value, (char **)NULL, 10);
+ stat->cmd_get= strtoll(value, (char **)NULL, 10);
}
else if (!memcmp("cmd_set", key, strlen("cmd_set")))
{
- //stat->cmd_set= strtoll(value, (char **)NULL, 10);
+ stat->cmd_set= strtoll(value, (char **)NULL, 10);
}
else if (!memcmp("get_hits", key, strlen("get_hits")))
{
- //stat->get_hits= strtoll(value, (char **)NULL, 10);
+ stat->get_hits= strtoll(value, (char **)NULL, 10);
}
else if (!memcmp("get_misses", key, strlen("get_misses")))
{
- //stat->get_misses= (uint64_t)strtoll(value, (char **)NULL, 10);
+ stat->get_misses= (uint64_t)strtoll(value, (char **)NULL, 10);
}
else if (!memcmp("evictions", key, strlen("evictions")))
{
- //stat->evictions= (uint64_t)strtoll(value, (char **)NULL, 10);
+ stat->evictions= (uint64_t)strtoll(value, (char **)NULL, 10);
}
else if (!memcmp("bytes_read", key, strlen("bytes_read")))
{
}
else if (!memcmp("limit_maxbytes", key, strlen("limit_maxbytes")))
{
- //stat->limit_maxbytes= strtol(value, (char **)NULL, 10);
+ stat->limit_maxbytes= strtol(value, (char **)NULL, 10);
}
else if (!memcmp("threads", key, strlen("threads")))
{
return MEMCACHED_SUCCESS;
}
+memcached_return pre_hsieh(memcached_st *memc)
+{
+ memcached_hash value= MEMCACHED_HASH_HSIEH;
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, &value);
+
+ return MEMCACHED_SUCCESS;
+}
+
memcached_return pre_hash_fnv1_64(memcached_st *memc)
{
memcached_hash value= MEMCACHED_HASH_FNV1_64;
{"nodelay", pre_nodelay, 0, tests},
{"md5", pre_md5, 0, tests},
{"crc", pre_crc, 0, tests},
+ {"hsieh", pre_hsieh, 0, tests},
{"fnv1_64", pre_hash_fnv1_64, 0, tests},
{"fnv1a_64", pre_hash_fnv1a_64, 0, tests},
{"fnv1_32", pre_hash_fnv1_32, 0, tests},
{"result", 0, 0, result_tests},
{"user", 0, 0, user_tests},
{"generate", 0, 0, generate_tests},
+ {"generate_hsieh", pre_hsieh, 0, generate_tests},
{"generate_nonblock", pre_nonblock, 0, generate_tests},
{0, 0, 0, 0}
};