Skip to content

Commit d2676b4

Browse files
zwChandormando
authored andcommitted
use item lock instead of global lock when hash expanding.
1 parent 4ceefe3 commit d2676b4

File tree

3 files changed

+46
-36
lines changed

3 files changed

+46
-36
lines changed

assoc.c

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ static void assoc_expand(void) {
146146
static void assoc_start_expand(void) {
147147
if (started_expanding)
148148
return;
149+
150+
/*With this condition, we can expanding holding only one item lock,
151+
* and it should always be false*/
152+
if (item_lock_hashpower >= hashpower)
153+
return;
154+
149155
started_expanding = true;
150156
pthread_cond_signal(&maintenance_cond);
151157
}
@@ -206,54 +212,57 @@ static void *assoc_maintenance_thread(void *arg) {
206212
while (do_run_maintenance_thread) {
207213
int ii = 0;
208214

209-
/* Lock the cache, and bulk move multiple buckets to the new
210-
* hash table. */
211-
item_lock_global();
212-
mutex_lock(&cache_lock);
213-
215+
/* As there is only one thread process expanding, and we hold the item
216+
* lock, it seems not necessary to hold the cache_lock . */
214217
for (ii = 0; ii < hash_bulk_move && expanding; ++ii) {
215218
item *it, *next;
216219
int bucket;
217-
218-
for (it = old_hashtable[expand_bucket]; NULL != it; it = next) {
219-
next = it->h_next;
220-
221-
bucket = hash(ITEM_key(it), it->nkey) & hashmask(hashpower);
222-
it->h_next = primary_hashtable[bucket];
223-
primary_hashtable[bucket] = it;
220+
void *item_lock = NULL;
221+
222+
/* bucket = hv & hashmask(hashpower) =>the bucket of hash table
223+
* is the lowest N bits of the hv, and the bucket of item_locks is
224+
* also the lowest M bits of hv, and N is greater than M.
225+
* So we can process expanding with only one item_lock. cool! */
226+
/*Get item lock for the slot in old hashtable*/
227+
if ((item_lock = item_trylock(expand_bucket))) {
228+
for (it = old_hashtable[expand_bucket]; NULL != it; it = next) {
229+
next = it->h_next;
230+
bucket = hash(ITEM_key(it), it->nkey) & hashmask(hashpower);
231+
it->h_next = primary_hashtable[bucket];
232+
primary_hashtable[bucket] = it;
233+
}
234+
235+
old_hashtable[expand_bucket] = NULL;
236+
237+
expand_bucket++;
238+
if (expand_bucket == hashsize(hashpower - 1)) {
239+
expanding = false;
240+
free(old_hashtable);
241+
STATS_LOCK();
242+
stats.hash_bytes -= hashsize(hashpower - 1) * sizeof(void *);
243+
stats.hash_is_expanding = 0;
244+
STATS_UNLOCK();
245+
if (settings.verbose > 1)
246+
fprintf(stderr, "Hash table expansion done\n");
247+
}
248+
249+
} else {
250+
/*wait for 100ms. since only one expanding thread, it's not
251+
* necessary to sleep a random value*/
252+
usleep(100*1000);
224253
}
225254

226-
old_hashtable[expand_bucket] = NULL;
227-
228-
expand_bucket++;
229-
if (expand_bucket == hashsize(hashpower - 1)) {
230-
expanding = false;
231-
free(old_hashtable);
232-
STATS_LOCK();
233-
stats.hash_bytes -= hashsize(hashpower - 1) * sizeof(void *);
234-
stats.hash_is_expanding = 0;
235-
STATS_UNLOCK();
236-
if (settings.verbose > 1)
237-
fprintf(stderr, "Hash table expansion done\n");
255+
if (item_lock) {
256+
item_trylock_unlock(item_lock);
257+
item_lock = NULL;
238258
}
239259
}
240260

241-
mutex_unlock(&cache_lock);
242-
item_unlock_global();
243-
244261
if (!expanding) {
245-
/* finished expanding. tell all threads to use fine-grained locks */
246-
switch_item_lock_type(ITEM_LOCK_GRANULAR);
247-
slabs_rebalancer_resume();
248262
/* We are done expanding.. just wait for next invocation */
249263
mutex_lock(&cache_lock);
250264
started_expanding = false;
251265
pthread_cond_wait(&maintenance_cond, &cache_lock);
252-
/* Before doing anything, tell threads to use a global lock */
253-
mutex_unlock(&cache_lock);
254-
slabs_rebalancer_pause();
255-
switch_item_lock_type(ITEM_LOCK_GLOBAL);
256-
mutex_lock(&cache_lock);
257266
assoc_expand();
258267
mutex_unlock(&cache_lock);
259268
}

assoc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ void do_assoc_move_next_bucket(void);
77
int start_assoc_maintenance_thread(void);
88
void stop_assoc_maintenance_thread(void);
99
extern unsigned int hashpower;
10+
extern unsigned int item_lock_hashpower;

thread.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static pthread_mutex_t cqi_freelist_lock;
5656
static pthread_mutex_t *item_locks;
5757
/* size of the item lock hash table */
5858
static uint32_t item_lock_count;
59-
static unsigned int item_lock_hashpower;
59+
unsigned int item_lock_hashpower;
6060
#define hashsize(n) ((unsigned long int)1<<(n))
6161
#define hashmask(n) (hashsize(n)-1)
6262
/* this lock is temporarily engaged during a hash table expansion */

0 commit comments

Comments
 (0)