summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2011-10-12 20:18:06 -0700
committerdormando <dormando@rydia.net>2011-11-09 16:06:08 -0800
commit97409b31af844e0ae8c9b2498276af8094151389 (patch)
tree47ff7ede01e972e15c4d97ddb1fcf1e03e82ae36
parent09f54cb4bdbe629fba8446ca20c82baeff8be7c7 (diff)
downloadmemcached-97409b31af844e0ae8c9b2498276af8094151389.tar.gz
Use a proper hash mask for item lock table
Directly use the hash for accessing the table. Performance seems unchanged from before but this is more proper. It also scales the hash table a bit as worker threads are increased.
-rw-r--r--thread.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/thread.c b/thread.c
index cce176b..59063e6 100644
--- a/thread.c
+++ b/thread.c
@@ -47,8 +47,10 @@ static CQ_ITEM *cqi_freelist;
static pthread_mutex_t cqi_freelist_lock;
static pthread_mutex_t *item_locks;
-/* TODO: Make this a function of the # of threads */
-#define ITEM_LOCKS 4000
+/* size of the item lock hash table */
+static uint32_t item_lock_count;
+/* size - 1 for lookup masking */
+static uint32_t item_lock_mask;
static LIBEVENT_DISPATCHER_THREAD dispatcher_thread;
@@ -69,11 +71,11 @@ static pthread_cond_t init_cond;
static void thread_libevent_process(int fd, short which, void *arg);
void item_lock(uint32_t hv) {
- mutex_lock(&item_locks[hv % ITEM_LOCKS]);
+ mutex_lock(&item_locks[hv & item_lock_mask]);
}
void item_unlock(uint32_t hv) {
- pthread_mutex_unlock(&item_locks[hv % ITEM_LOCKS]);
+ pthread_mutex_unlock(&item_locks[hv & item_lock_mask]);
}
/*
@@ -623,6 +625,7 @@ void slab_stats_aggregate(struct thread_stats *stats, struct slab_stats *out) {
*/
void thread_init(int nthreads, struct event_base *main_base) {
int i;
+ int power;
pthread_mutex_init(&cache_lock, NULL);
pthread_mutex_init(&stats_lock, NULL);
@@ -633,12 +636,27 @@ void thread_init(int nthreads, struct event_base *main_base) {
pthread_mutex_init(&cqi_freelist_lock, NULL);
cqi_freelist = NULL;
- item_locks = calloc(ITEM_LOCKS, sizeof(pthread_mutex_t));
+ /* Want a wide lock table, but don't waste memory */
+ if (nthreads < 3) {
+ power = 10;
+ } else if (nthreads < 4) {
+ power = 11;
+ } else if (nthreads < 5) {
+ power = 12;
+ } else {
+ /* 8192 buckets, and central locks don't scale much past 5 threads */
+ power = 13;
+ }
+
+ item_lock_count = ((unsigned long int)1 << (power));
+ item_lock_mask = item_lock_count - 1;
+
+ item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t));
if (! item_locks) {
perror("Can't allocate item locks");
exit(1);
}
- for (i = 0; i < ITEM_LOCKS; i++) {
+ for (i = 0; i < item_lock_count; i++) {
pthread_mutex_init(&item_locks[i], NULL);
}