Skip to content

Commit

Permalink
move hash calls outside of cache_lock
Browse files Browse the repository at this point in the history
been hard to measure while using the intel hash (since it's very fast), but
should help with the software hash.
  • Loading branch information
dormando committed Nov 10, 2011
1 parent 45e0e95 commit bab9acd
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 58 deletions.
16 changes: 6 additions & 10 deletions assoc.c
Expand Up @@ -73,8 +73,7 @@ void assoc_init(const int hashtable_init) {
STATS_UNLOCK();
}

item *assoc_find(const char *key, const size_t nkey) {
uint32_t hv = hash(key, nkey, 0);
item *assoc_find(const char *key, const size_t nkey, const uint32_t hv) {
item *it;
unsigned int oldbucket;

Expand Down Expand Up @@ -103,8 +102,7 @@ item *assoc_find(const char *key, const size_t nkey) {
/* returns the address of the item pointer before the key. if *item == 0,
the item wasn't found */

static item** _hashitem_before (const char *key, const size_t nkey) {
uint32_t hv = hash(key, nkey, 0);
static item** _hashitem_before (const char *key, const size_t nkey, const uint32_t hv) {
item **pos;
unsigned int oldbucket;

Expand Down Expand Up @@ -146,13 +144,11 @@ static void assoc_expand(void) {
}

/* Note: this isn't an assoc_update. The key must not already exist to call this */
int assoc_insert(item *it) {
uint32_t hv;
int assoc_insert(item *it, const uint32_t hv) {
unsigned int oldbucket;

assert(assoc_find(ITEM_key(it), it->nkey) == 0); /* shouldn't have duplicately named things defined */
// assert(assoc_find(ITEM_key(it), it->nkey) == 0); /* shouldn't have duplicately named things defined */

hv = hash(ITEM_key(it), it->nkey, 0);
if (expanding &&
(oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket)
{
Expand All @@ -172,8 +168,8 @@ int assoc_insert(item *it) {
return 1;
}

void assoc_delete(const char *key, const size_t nkey) {
item **before = _hashitem_before(key, nkey);
void assoc_delete(const char *key, const size_t nkey, const uint32_t hv) {
item **before = _hashitem_before(key, nkey, hv);

if (*before) {
item *nxt;
Expand Down
6 changes: 3 additions & 3 deletions assoc.h
@@ -1,8 +1,8 @@
/* associative array */
void assoc_init(const int hashpower_init);
item *assoc_find(const char *key, const size_t nkey);
int assoc_insert(item *item);
void assoc_delete(const char *key, const size_t nkey);
item *assoc_find(const char *key, const size_t nkey, const uint32_t hv);
int assoc_insert(item *item, const uint32_t hv);
void assoc_delete(const char *key, const size_t nkey, const uint32_t hv);
void do_assoc_move_next_bucket(void);
int start_assoc_maintenance_thread(void);
void stop_assoc_maintenance_thread(void);
Expand Down
42 changes: 22 additions & 20 deletions items.c
Expand Up @@ -125,7 +125,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
}
it->refcount = 1;
slabs_adjust_mem_requested(it->slabs_clsid, ITEM_ntotal(it), ntotal);
do_item_unlink(it);
do_item_unlink(it, hash(ITEM_key(it), it->nkey, 0));
/* Initialize the item block: */
it->slabs_clsid = 0;
it->refcount = 0;
Expand Down Expand Up @@ -189,7 +189,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
itemstats[id].expired_unfetched++;
}
}
do_item_unlink(search);
do_item_unlink(search, hash(ITEM_key(search), search->nkey, 0));
break;
}
}
Expand All @@ -208,7 +208,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
if (search->refcount != 0 && search->time + TAIL_REPAIR_TIME < current_time) {
itemstats[id].tailrepairs++;
search->refcount = 0;
do_item_unlink(search);
do_item_unlink(search, hash(ITEM_key(search), search->nkey, 0));
break;
}
}
Expand Down Expand Up @@ -312,12 +312,12 @@ static void item_unlink_q(item *it) {
return;
}

int do_item_link(item *it) {
int do_item_link(item *it, const uint32_t hv) {
MEMCACHED_ITEM_LINK(ITEM_key(it), it->nkey, it->nbytes);
assert((it->it_flags & (ITEM_LINKED|ITEM_SLABBED)) == 0);
it->it_flags |= ITEM_LINKED;
it->time = current_time;
assoc_insert(it);
assoc_insert(it, hv);

STATS_LOCK();
stats.curr_bytes += ITEM_ntotal(it);
Expand All @@ -333,15 +333,15 @@ int do_item_link(item *it) {
return 1;
}

void do_item_unlink(item *it) {
void do_item_unlink(item *it, const uint32_t hv) {
MEMCACHED_ITEM_UNLINK(ITEM_key(it), it->nkey, it->nbytes);
if ((it->it_flags & ITEM_LINKED) != 0) {
it->it_flags &= ~ITEM_LINKED;
STATS_LOCK();
stats.curr_bytes -= ITEM_ntotal(it);
stats.curr_items -= 1;
STATS_UNLOCK();
assoc_delete(ITEM_key(it), it->nkey);
assoc_delete(ITEM_key(it), it->nkey, hv);
item_unlink_q(it);
if (it->refcount == 0) item_free(it);
}
Expand Down Expand Up @@ -372,13 +372,13 @@ void do_item_update(item *it) {
}
}

int do_item_replace(item *it, item *new_it) {
int do_item_replace(item *it, item *new_it, const uint32_t hv) {
MEMCACHED_ITEM_REPLACE(ITEM_key(it), it->nkey, it->nbytes,
ITEM_key(new_it), new_it->nkey, new_it->nbytes);
assert((it->it_flags & ITEM_SLABBED) == 0);

do_item_unlink(it);
return do_item_link(new_it);
do_item_unlink(it, hv);
return do_item_link(new_it, hv);
}

/*@null@*/
Expand Down Expand Up @@ -439,7 +439,8 @@ void do_item_stats(ADD_STAT add_stats, void *c) {
tails[i]->exptime < current_time))) {
--search;
if (tails[i]->refcount == 0) {
do_item_unlink(tails[i]);
do_item_unlink(tails[i], hash(ITEM_key(tails[i]),
tails[i]->nkey, 0));
} else {
break;
}
Expand Down Expand Up @@ -510,8 +511,8 @@ void do_item_stats_sizes(ADD_STAT add_stats, void *c) {
}

/** wrapper around assoc_find which does the lazy expiration logic */
item *do_item_get(const char *key, const size_t nkey) {
item *it = assoc_find(key, nkey);
item *do_item_get(const char *key, const size_t nkey, const uint32_t hv) {
item *it = assoc_find(key, nkey, hv);
int was_found = 0;

if (settings.verbose > 2) {
Expand All @@ -525,7 +526,7 @@ item *do_item_get(const char *key, const size_t nkey) {

if (it != NULL && settings.oldest_live != 0 && settings.oldest_live <= current_time &&
it->time <= settings.oldest_live) {
do_item_unlink(it); /* MTSAFE - cache_lock held */
do_item_unlink(it, hv); /* MTSAFE - cache_lock held */
it = NULL;
}

Expand All @@ -535,7 +536,7 @@ item *do_item_get(const char *key, const size_t nkey) {
}

if (it != NULL && it->exptime != 0 && it->exptime <= current_time) {
do_item_unlink(it); /* MTSAFE - cache_lock held */
do_item_unlink(it, hv); /* MTSAFE - cache_lock held */
it = NULL;
}

Expand All @@ -556,17 +557,18 @@ item *do_item_get(const char *key, const size_t nkey) {
return it;
}

item *do_item_touch(const char *key, size_t nkey, uint32_t exptime) {
item *it = do_item_get(key, nkey);
item *do_item_touch(const char *key, size_t nkey, uint32_t exptime,
const uint32_t hv) {
item *it = do_item_get(key, nkey, hv);
if (it != NULL) {
it->exptime = exptime;
}
return it;
}

/** returns an item whether or not it's expired. */
item *do_item_get_nocheck(const char *key, const size_t nkey) {
item *it = assoc_find(key, nkey);
item *do_item_get_nocheck(const char *key, const size_t nkey, const uint32_t hv) {
item *it = assoc_find(key, nkey, hv);
if (it) {
it->refcount++;
DEBUG_REFCNT(it, '+');
Expand All @@ -590,7 +592,7 @@ void do_item_flush_expired(void) {
if (iter->time >= settings.oldest_live) {
next = iter->next;
if ((iter->it_flags & ITEM_SLABBED) == 0) {
do_item_unlink(iter);
do_item_unlink(iter, hash(ITEM_key(iter), iter->nkey, 0));
}
} else {
/* We've hit the first old item. Continue to the next queue. */
Expand Down
12 changes: 6 additions & 6 deletions items.h
Expand Up @@ -6,11 +6,11 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
void item_free(item *it);
bool item_size_ok(const size_t nkey, const int flags, const int nbytes);

int do_item_link(item *it); /** may fail if transgresses limits */
void do_item_unlink(item *it);
int do_item_link(item *it, const uint32_t hv); /** may fail if transgresses limits */
void do_item_unlink(item *it, const uint32_t hv);
void do_item_remove(item *it);
void do_item_update(item *it); /** update LRU time to current and reposition */
int do_item_replace(item *it, item *new_it);
int do_item_replace(item *it, item *new_it, const uint32_t hv);

/*@null@*/
char *do_item_cachedump(const unsigned int slabs_clsid, const unsigned int limit, unsigned int *bytes);
Expand All @@ -19,8 +19,8 @@ void do_item_stats(ADD_STAT add_stats, void *c);
void do_item_stats_sizes(ADD_STAT add_stats, void *c);
void do_item_flush_expired(void);

item *do_item_get(const char *key, const size_t nkey);
item *do_item_get_nocheck(const char *key, const size_t nkey);
item *do_item_touch(const char *key, const size_t nkey, uint32_t exptime);
item *do_item_get(const char *key, const size_t nkey, const uint32_t hv);
item *do_item_get_nocheck(const char *key, const size_t nkey, const uint32_t hv);
item *do_item_touch(const char *key, const size_t nkey, uint32_t exptime, const uint32_t hv);
void item_stats_reset(void);
extern pthread_mutex_t cache_lock;
17 changes: 9 additions & 8 deletions memcached.c
Expand Up @@ -2242,9 +2242,9 @@ static void complete_nread(conn *c) {
*
* Returns the state of storage.
*/
enum store_item_type do_store_item(item *it, int comm, conn *c) {
enum store_item_type do_store_item(item *it, int comm, conn *c, const uint32_t hv) {
char *key = ITEM_key(it);
item *old_it = do_item_get(key, it->nkey);
item *old_it = do_item_get(key, it->nkey, hv);
enum store_item_type stored = NOT_STORED;

item *new_it = NULL;
Expand Down Expand Up @@ -2274,7 +2274,7 @@ enum store_item_type do_store_item(item *it, int comm, conn *c) {
c->thread->stats.slab_stats[old_it->slabs_clsid].cas_hits++;
pthread_mutex_unlock(&c->thread->stats.mutex);

item_replace(old_it, it);
item_replace(old_it, it, hv);
stored = STORED;
} else {
pthread_mutex_lock(&c->thread->stats.mutex);
Expand Down Expand Up @@ -2337,9 +2337,9 @@ enum store_item_type do_store_item(item *it, int comm, conn *c) {

if (stored == NOT_STORED) {
if (old_it != NULL)
item_replace(old_it, it);
item_replace(old_it, it, hv);
else
do_item_link(it);
do_item_link(it, hv);

c->cas = ITEM_get_cas(it);

Expand Down Expand Up @@ -3032,13 +3032,14 @@ static void process_arithmetic_command(conn *c, token_t *tokens, const size_t nt
*/
enum delta_result_type do_add_delta(conn *c, const char *key, const size_t nkey,
const bool incr, const int64_t delta,
char *buf, uint64_t *cas) {
char *buf, uint64_t *cas,
const uint32_t hv) {
char *ptr;
uint64_t value;
int res;
item *it;

it = do_item_get(key, nkey);
it = do_item_get(key, nkey, hv);
if (!it) {
return DELTA_ITEM_NOT_FOUND;
}
Expand Down Expand Up @@ -3086,7 +3087,7 @@ enum delta_result_type do_add_delta(conn *c, const char *key, const size_t nkey,
}
memcpy(ITEM_data(new_it), buf, res);
memcpy(ITEM_data(new_it) + res, "\r\n", 2);
item_replace(it, new_it);
item_replace(it, new_it, hv);
// Overwrite the older item's CAS with our new CAS since we're
// returning the CAS of the old item below.
ITEM_set_cas(it, (settings.use_cas) ? ITEM_get_cas(new_it) : 0);
Expand Down
6 changes: 3 additions & 3 deletions memcached.h
Expand Up @@ -459,8 +459,8 @@ void do_accept_new_conns(const bool do_accept);
enum delta_result_type do_add_delta(conn *c, const char *key,
const size_t nkey, const bool incr,
const int64_t delta, char *buf,
uint64_t *cas);
enum store_item_type do_store_item(item *item, int comm, conn* c);
uint64_t *cas, const uint32_t hv);
enum store_item_type do_store_item(item *item, int comm, conn* c, const uint32_t hv);
conn *conn_new(const int sfd, const enum conn_states init_state, const int event_flags, const int read_buffer_size, enum network_transport transport, struct event_base *base);
extern int daemonize(int nochdir, int noclose);

Expand Down Expand Up @@ -507,7 +507,7 @@ item *item_get(const char *key, const size_t nkey);
item *item_touch(const char *key, const size_t nkey, uint32_t exptime);
int item_link(item *it);
void item_remove(item *it);
int item_replace(item *it, item *new_it);
int item_replace(item *it, item *new_it, const uint32_t hv);
void item_stats(ADD_STAT add_stats, void *c);
void item_stats_sizes(ADD_STAT add_stats, void *c);
void item_unlink(item *it);
Expand Down
28 changes: 20 additions & 8 deletions thread.c
Expand Up @@ -340,16 +340,20 @@ item *item_alloc(char *key, size_t nkey, int flags, rel_time_t exptime, int nbyt
*/
item *item_get(const char *key, const size_t nkey) {
item *it;
uint32_t hv;
hv = hash(key, nkey, 0);
mutex_lock(&cache_lock);
it = do_item_get(key, nkey);
it = do_item_get(key, nkey, hv);
pthread_mutex_unlock(&cache_lock);
return it;
}

item *item_touch(const char *key, size_t nkey, uint32_t exptime) {
item *it;
uint32_t hv;
hv = hash(key, nkey, 0);
mutex_lock(&cache_lock);
it = do_item_touch(key, nkey, exptime);
it = do_item_touch(key, nkey, exptime, hv);
pthread_mutex_unlock(&cache_lock);
return it;
}
Expand All @@ -359,9 +363,11 @@ item *item_touch(const char *key, size_t nkey, uint32_t exptime) {
*/
int item_link(item *item) {
int ret;
uint32_t hv;

hv = hash(ITEM_key(item), item->nkey, 0);
mutex_lock(&cache_lock);
ret = do_item_link(item);
ret = do_item_link(item, hv);
pthread_mutex_unlock(&cache_lock);
return ret;
}
Expand All @@ -381,16 +387,18 @@ void item_remove(item *item) {
* Unprotected by a mutex lock since the core server does not require
* it to be thread-safe.
*/
int item_replace(item *old_it, item *new_it) {
return do_item_replace(old_it, new_it);
int item_replace(item *old_it, item *new_it, const uint32_t hv) {
return do_item_replace(old_it, new_it, hv);
}

/*
* Unlinks an item from the LRU and hashtable.
*/
void item_unlink(item *item) {
uint32_t hv;
hv = hash(ITEM_key(item), item->nkey, 0);
mutex_lock(&cache_lock);
do_item_unlink(item);
do_item_unlink(item, hv);
pthread_mutex_unlock(&cache_lock);
}

Expand All @@ -411,9 +419,11 @@ enum delta_result_type add_delta(conn *c, const char *key,
const int64_t delta, char *buf,
uint64_t *cas) {
enum delta_result_type ret;
uint32_t hv;

hv = hash(key, nkey, 0);
mutex_lock(&cache_lock);
ret = do_add_delta(c, key, nkey, incr, delta, buf, cas);
ret = do_add_delta(c, key, nkey, incr, delta, buf, cas, hv);
pthread_mutex_unlock(&cache_lock);
return ret;
}
Expand All @@ -423,9 +433,11 @@ enum delta_result_type add_delta(conn *c, const char *key,
*/
enum store_item_type store_item(item *item, int comm, conn* c) {
enum store_item_type ret;
uint32_t hv;

hv = hash(ITEM_key(item), item->nkey, 0);
mutex_lock(&cache_lock);
ret = do_store_item(item, comm, c);
ret = do_store_item(item, comm, c, hv);
pthread_mutex_unlock(&cache_lock);
return ret;
}
Expand Down

0 comments on commit bab9acd

Please sign in to comment.