From bab9acd115828e44176a3671bd65089d6fdeff85 Mon Sep 17 00:00:00 2001 From: dormando Date: Sun, 2 Oct 2011 01:23:46 -0700 Subject: [PATCH] move hash calls outside of cache_lock been hard to measure while using the intel hash (since it's very fast), but should help with the software hash. --- assoc.c | 16 ++++++---------- assoc.h | 6 +++--- items.c | 42 ++++++++++++++++++++++-------------------- items.h | 12 ++++++------ memcached.c | 17 +++++++++-------- memcached.h | 6 +++--- thread.c | 28 ++++++++++++++++++++-------- 7 files changed, 69 insertions(+), 58 deletions(-) diff --git a/assoc.c b/assoc.c index 59cbb0f029..3530a62b52 100644 --- a/assoc.c +++ b/assoc.c @@ -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; @@ -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; @@ -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) { @@ -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; diff --git a/assoc.h b/assoc.h index 031958b5dd..ccdfdd5a35 100644 --- a/assoc.h +++ b/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); diff --git a/items.c b/items.c index d655e5ecfd..e42420d8c4 100644 --- a/items.c +++ b/items.c @@ -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; @@ -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; } } @@ -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; } } @@ -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); @@ -333,7 +333,7 @@ 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; @@ -341,7 +341,7 @@ void do_item_unlink(item *it) { 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); } @@ -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@*/ @@ -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; } @@ -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) { @@ -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; } @@ -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; } @@ -556,8 +557,9 @@ 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; } @@ -565,8 +567,8 @@ item *do_item_touch(const char *key, size_t nkey, uint32_t exptime) { } /** 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, '+'); @@ -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. */ diff --git a/items.h b/items.h index 447aeedabc..acc1ef588d 100644 --- a/items.h +++ b/items.h @@ -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); @@ -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; diff --git a/memcached.c b/memcached.c index 0c1db666cc..60c89b73b6 100644 --- a/memcached.c +++ b/memcached.c @@ -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; @@ -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); @@ -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); @@ -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; } @@ -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); diff --git a/memcached.h b/memcached.h index 628f0434c0..b6c20f2679 100644 --- a/memcached.h +++ b/memcached.h @@ -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); @@ -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); diff --git a/thread.c b/thread.c index ff1e898680..efcc739a7e 100644 --- a/thread.c +++ b/thread.c @@ -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; } @@ -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; } @@ -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); } @@ -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; } @@ -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; }