From: Ripduman Sohan <[email protected]> Basic idea - compute hash and store within item_hash, reduces computation overhead in subsequent operations. Also reduces the time spent in the cu_op_recs.lock.
Signed-off-by: Ripduman Sohan <[email protected]> --- engines/default_engine/items.c | 100 ++++++++++++++++++++-------------------- engines/default_engine/items.h | 10 ++-- 2 files changed, 54 insertions(+), 56 deletions(-) diff --git a/engines/default_engine/items.c b/engines/default_engine/items.c index 3b623fa..86b78b9 100644 --- a/engines/default_engine/items.c +++ b/engines/default_engine/items.c @@ -15,12 +15,12 @@ static void item_link_q(struct default_engine *engine, hash_item *it); static void item_unlink_q(struct default_engine *engine, hash_item *it); static hash_item *do_item_alloc(struct default_engine *engine, - const void *key, const size_t nkey, + uint32_t hash, const void *key, const size_t nkey, const int flags, const rel_time_t exptime, const int nbytes, const void *cookie); static hash_item *do_item_get(struct default_engine *engine, - const char *key, const size_t nkey); + uint32_t hash, const char *key, const size_t nkey); static int do_item_link(struct default_engine *engine, hash_item *it); static void do_item_unlink(struct default_engine *engine, hash_item *it); static void do_item_release(struct default_engine *engine, hash_item *it); @@ -28,8 +28,8 @@ static void do_item_update(struct default_engine *engine, hash_item *it); static int do_item_replace(struct default_engine *engine, hash_item *it, hash_item *new_it); static void item_free(struct default_engine *engine, hash_item *it); -static void acquire_key_operation_mutex(struct default_engine *engine, const char *key, size_t nkey); -static void release_key_operation_mutex(struct default_engine *engine, const char *key, size_t nkey); +static void acquire_key_operation_mutex(struct default_engine *engine, uint32_t hash); +static void release_key_operation_mutex(struct default_engine *engine, uint32_t hash); /* Macros to clarify the items datastructure LRU list acquisition and release */ #define lock_lru_list(engine, listid) pthread_mutex_lock(&engine->items.lock[listid]) @@ -84,6 +84,7 @@ static uint64_t get_cas_id(void) { /*@null@*/ hash_item *do_item_alloc(struct default_engine *engine, + const uint32_t hash, const void *key, const size_t nkey, const int flags, @@ -247,6 +248,7 @@ hash_item *do_item_alloc(struct default_engine *engine, it->flags = flags; memcpy((void*)item_get_key(it), key, nkey); it->exptime = exptime; + it->hash = hash; return it; } @@ -313,9 +315,7 @@ int do_item_link(struct default_engine *engine, hash_item *it) { assert(it->nbytes < (1024 * 1024)); /* 1MB max size */ it->iflag |= ITEM_LINKED; it->time = engine->server.core->get_current_time(); - assoc_insert(engine, engine->server.core->hash(item_get_key(it), - it->nkey, 0), - it); + assoc_insert(engine, it->hash, it); pthread_mutex_lock(&engine->stats.lock); engine->stats.curr_bytes += ITEM_ntotal(engine, it); @@ -339,9 +339,7 @@ void do_item_unlink(struct default_engine *engine, hash_item *it) { engine->stats.curr_bytes -= ITEM_ntotal(engine, it); engine->stats.curr_items -= 1; pthread_mutex_unlock(&engine->stats.lock); - assoc_delete(engine, engine->server.core->hash(item_get_key(it), - it->nkey, 0), - item_get_key(it), it->nkey); + assoc_delete(engine, it->hash, item_get_key(it), it->nkey); item_unlink_q(engine, it); if (it->refcount == 0) { item_free(engine, it); @@ -537,11 +535,9 @@ static void do_item_stats_sizes(struct default_engine *engine, /** wrapper around assoc_find which does the lazy expiration logic */ hash_item *do_item_get(struct default_engine *engine, - const char *key, const size_t nkey) { + uint32_t hash, const char *key, const size_t nkey) { rel_time_t current_time = engine->server.core->get_current_time(); - hash_item *it = assoc_find(engine, engine->server.core->hash(key, - nkey, 0), - key, nkey); + hash_item *it = assoc_find(engine, hash, key, nkey); int was_found = 0; if (engine->config.verbose > 2) { @@ -610,7 +606,7 @@ static ENGINE_ERROR_CODE do_store_item(struct default_engine *engine, ENGINE_STORE_OPERATION operation, const void *cookie) { const char *key = item_get_key(it); - hash_item *old_it = do_item_get(engine, key, it->nkey); + hash_item *old_it = do_item_get(engine, it->hash, key, it->nkey); ENGINE_ERROR_CODE stored = ENGINE_NOT_STORED; hash_item *new_it = NULL; @@ -663,7 +659,7 @@ static ENGINE_ERROR_CODE do_store_item(struct default_engine *engine, if (stored == ENGINE_NOT_STORED) { /* we have it and old_it here - alloc memory to hold both */ - new_it = do_item_alloc(engine, key, it->nkey, + new_it = do_item_alloc(engine, it->hash, key, it->nkey, old_it->flags, old_it->exptime, it->nbytes + old_it->nbytes, @@ -777,7 +773,7 @@ static ENGINE_ERROR_CODE do_add_delta(struct default_engine *engine, item_set_cas(NULL, NULL, it, get_cas_id()); *rcas = item_get_cas(it); } else { - hash_item *new_it = do_item_alloc(engine, item_get_key(it), + hash_item *new_it = do_item_alloc(engine, it->hash, item_get_key(it), it->nkey, it->flags, it->exptime, res, cookie); @@ -805,9 +801,10 @@ hash_item *item_alloc(struct default_engine *engine, const void *key, size_t nkey, int flags, rel_time_t exptime, int nbytes, const void *cookie) { hash_item *it; - acquire_key_operation_mutex(engine, key, nkey); - it = do_item_alloc(engine, key, nkey, flags, exptime, nbytes, cookie); - release_key_operation_mutex(engine, key, nkey); + uint32_t hash = engine->server.core->hash(key, nkey, 0); + acquire_key_operation_mutex(engine, hash); + it = do_item_alloc(engine, hash, key, nkey, flags, exptime, nbytes, cookie); + release_key_operation_mutex(engine, hash); return it; } @@ -818,9 +815,10 @@ hash_item *item_alloc(struct default_engine *engine, hash_item *item_get(struct default_engine *engine, const void *key, const size_t nkey) { hash_item *it; - acquire_key_operation_mutex(engine, key, nkey); - it = do_item_get(engine, key, nkey); - release_key_operation_mutex(engine, key, nkey); + uint32_t hash = engine->server.core->hash(key, nkey, 0); + acquire_key_operation_mutex(engine, hash); + it = do_item_get(engine, hash, key, nkey); + release_key_operation_mutex(engine, hash); return it; } @@ -829,24 +827,25 @@ hash_item *item_get(struct default_engine *engine, * needed. */ void item_release(struct default_engine *engine, hash_item *item) { - acquire_key_operation_mutex(engine, item_get_key(item), item->nkey); + acquire_key_operation_mutex(engine, item->hash); do_item_release(engine, item); - release_key_operation_mutex(engine, item_get_key(item), item->nkey); + release_key_operation_mutex(engine, item->hash); } /* * Unlinks an item from the LRU and hashtable. */ void item_unlink(struct default_engine *engine, hash_item *item) { - acquire_key_operation_mutex(engine, item_get_key(item), item->nkey); + acquire_key_operation_mutex(engine, item->hash); lock_lru_list(engine, item->slabs_clsid); do_item_unlink(engine, item); unlock_lru_list(engine, item->slabs_clsid); - release_key_operation_mutex(engine, item_get_key(item), item->nkey); + release_key_operation_mutex(engine, item->hash); } static ENGINE_ERROR_CODE do_arithmetic(struct default_engine *engine, const void* cookie, + const uint32_t hash, const void* key, const int nkey, const bool increment, @@ -857,7 +856,7 @@ static ENGINE_ERROR_CODE do_arithmetic(struct default_engine *engine, uint64_t *cas, uint64_t *result) { - hash_item *item = do_item_get(engine, key, nkey); + hash_item *item = do_item_get(engine, hash, key, nkey); ENGINE_ERROR_CODE ret; if (item == NULL) { @@ -868,7 +867,7 @@ static ENGINE_ERROR_CODE do_arithmetic(struct default_engine *engine, int len = snprintf(buffer, sizeof(buffer), "%"PRIu64, (uint64_t)initial); - item = do_item_alloc(engine, key, nkey, 0, exptime, len, cookie); + item = do_item_alloc(engine, hash, key, nkey, 0, exptime, len, cookie); if (item == NULL) { return ENGINE_ENOMEM; } @@ -901,12 +900,12 @@ ENGINE_ERROR_CODE arithmetic(struct default_engine *engine, uint64_t *result) { ENGINE_ERROR_CODE ret; - - acquire_key_operation_mutex(engine, key, nkey); - ret = do_arithmetic(engine, cookie, key, nkey, increment, + uint32_t hash = engine->server.core->hash(key, nkey, 0); + acquire_key_operation_mutex(engine, hash); + ret = do_arithmetic(engine, cookie, hash, key, nkey, increment, create, delta, initial, exptime, cas, result); - release_key_operation_mutex(engine, key, nkey); + release_key_operation_mutex(engine, hash); return ret; } @@ -919,18 +918,19 @@ ENGINE_ERROR_CODE store_item(struct default_engine *engine, const void *cookie) { ENGINE_ERROR_CODE ret; - acquire_key_operation_mutex(engine, item_get_key(item), item->nkey); + acquire_key_operation_mutex(engine, item->hash); ret = do_store_item(engine, item, cas, operation, cookie); - release_key_operation_mutex(engine, item_get_key(item), item->nkey); + release_key_operation_mutex(engine, item->hash); return ret; } static hash_item *do_touch_item(struct default_engine *engine, + uint32_t hash, const void *key, uint16_t nkey, uint32_t exptime) { - hash_item *item = do_item_get(engine, key, nkey); + hash_item *item = do_item_get(engine, hash, key, nkey); if (item != NULL) { item->exptime = exptime; } @@ -943,10 +943,10 @@ hash_item *touch_item(struct default_engine *engine, uint32_t exptime) { hash_item *ret; - - acquire_key_operation_mutex(engine, key, nkey); - ret = do_touch_item(engine, key, nkey, exptime); - release_key_operation_mutex(engine, key, nkey); + uint32_t hash = engine->server.core->hash(key, nkey, 0); + acquire_key_operation_mutex(engine, hash); + ret = do_touch_item(engine, hash, key, nkey, exptime); + release_key_operation_mutex(engine, hash); return ret; } @@ -1279,10 +1279,13 @@ ENGINE_ERROR_CODE items_init(struct default_engine *engine, uint32_t num_threads engine->cur_op_recs.num_recs = num_threads; + for (int i = 0; i < engine->cur_op_recs.num_recs; i++) + engine->cur_op_recs.keys[i].hash = -1; + return ENGINE_SUCCESS; } -static void acquire_key_operation_mutex(struct default_engine *engine, const char *key, size_t nkey) +static void acquire_key_operation_mutex(struct default_engine *engine, uint32_t hash) { int i; int zero_index; @@ -1295,11 +1298,10 @@ start: for (i = 0; i < cur_op_recs->num_recs; i++) { - if (cur_op_recs->keys[i].nkey == 0) + if (cur_op_recs->keys[i].hash == -1) zero_index = i; - if (cur_op_recs->keys[i].nkey == nkey && - memcmp(cur_op_recs->keys[i].key, key, nkey) == 0) { + if (cur_op_recs->keys[i].hash == hash) { pthread_cond_wait(&cur_op_recs->key_wait_cv, &cur_op_recs->lock); goto start; } @@ -1308,12 +1310,11 @@ start: assert(zero_index != cur_op_recs->num_recs); - cur_op_recs->keys[zero_index].nkey = nkey; - memcpy(cur_op_recs->keys[zero_index].key, key, nkey); + cur_op_recs->keys[zero_index].hash = hash; pthread_mutex_unlock(&cur_op_recs->lock); } -static void release_key_operation_mutex(struct default_engine *engine, const char *key, size_t nkey) +static void release_key_operation_mutex(struct default_engine *engine, uint32_t hash) { int i; struct cur_op_recs *cur_op_recs = &engine->cur_op_recs; @@ -1322,10 +1323,9 @@ static void release_key_operation_mutex(struct default_engine *engine, const cha for (i = 0; i < cur_op_recs->num_recs; i++) { - if (cur_op_recs->keys[i].nkey == nkey && - memcmp(cur_op_recs->keys[i].key, key, nkey) == 0) + if (cur_op_recs->keys[i].hash == hash) { - cur_op_recs->keys[i].nkey = 0; + cur_op_recs->keys[i].hash = -1; break; } } diff --git a/engines/default_engine/items.h b/engines/default_engine/items.h index 6b02624..4ed6ea9 100644 --- a/engines/default_engine/items.h +++ b/engines/default_engine/items.h @@ -22,6 +22,7 @@ typedef struct _hash_item { * implementation. */ unsigned short refcount; uint8_t slabs_clsid;/* which slab class we're in */ + uint32_t hash; /* Hash of associated key */ } hash_item; typedef struct { @@ -42,16 +43,13 @@ struct items { pthread_mutex_t itemstats_lock; }; -struct cur_key_rec { - char key[KEY_MAX_LENGTH]; - size_t nkey; -}; - struct cur_op_recs { pthread_mutex_t lock; pthread_cond_t key_wait_cv; int num_recs; - struct cur_key_rec *keys; /* Dynamically allocated at runtime */ + struct { + int64_t hash; + } *keys; /* Dynamically allocated at runtime */ }; /** -- 1.7.1
