diff options
author | dormando <dormando@rydia.net> | 2017-01-08 16:55:16 -0800 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2017-01-22 19:57:15 -0800 |
commit | 2266c8402bd4f8a2f2a2da6a053c1d63a628e230 (patch) | |
tree | ea7c7a795d2da86906b95a7de4e8ca4be676dc03 /items.c | |
parent | fa8b42560aa948822514ed6560d8448623049297 (diff) | |
download | memcached-2266c8402bd4f8a2f2a2da6a053c1d63a628e230.tar.gz |
LRU maintainer performance: per-class sleep
Even if just one slab class is active, each wake of the LRU maintainer
thread would pull the tail of all available LRU's in all available slab
classes.
With this change they are independently scheduled, which should improve
throughput of the thread.
Diffstat (limited to 'items.c')
-rw-r--r-- | items.c | 46 |
1 files changed, 28 insertions, 18 deletions
@@ -52,7 +52,6 @@ static int stats_sizes_buckets = 0; static volatile int do_run_lru_maintainer_thread = 0; static int lru_maintainer_initialized = 0; -static int lru_maintainer_check_clsid = 0; static pthread_mutex_t lru_maintainer_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t cas_id_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t stats_sizes_lock = PTHREAD_MUTEX_INITIALIZER; @@ -1175,9 +1174,13 @@ static pthread_t lru_maintainer_tid; static void *lru_maintainer_thread(void *arg) { int i; useconds_t to_sleep = MIN_LRU_MAINTAINER_SLEEP; + useconds_t last_sleep = MIN_LRU_MAINTAINER_SLEEP; rel_time_t last_crawler_check = 0; + useconds_t next_juggles[MAX_NUMBER_OF_SLAB_CLASSES]; + useconds_t backoff_juggles[MAX_NUMBER_OF_SLAB_CLASSES]; struct crawler_expired_data cdata; memset(&cdata, 0, sizeof(struct crawler_expired_data)); + memset(next_juggles, 0, sizeof(next_juggles)); pthread_mutex_init(&cdata.lock, NULL); cdata.crawl_complete = true; // kick off the crawler. logger *l = logger_create(); @@ -1190,32 +1193,39 @@ static void *lru_maintainer_thread(void *arg) { if (settings.verbose > 2) fprintf(stderr, "Starting LRU maintainer background thread\n"); while (do_run_lru_maintainer_thread) { - int did_moves = 0; pthread_mutex_unlock(&lru_maintainer_lock); if (to_sleep) usleep(to_sleep); pthread_mutex_lock(&lru_maintainer_lock); + /* A sleep of zero counts as a minimum of a 1ms wait */ + last_sleep = to_sleep > 1000 ? to_sleep : 1000; + to_sleep = MAX_LRU_MAINTAINER_SLEEP; STATS_LOCK(); stats.lru_maintainer_juggles++; STATS_UNLOCK(); - /* We were asked to immediately wake up and poke a particular slab - * class due to a low watermark being hit */ - if (lru_maintainer_check_clsid != 0) { - did_moves = lru_maintainer_juggle(lru_maintainer_check_clsid); - lru_maintainer_check_clsid = 0; - } else { - for (i = POWER_SMALLEST; i < MAX_NUMBER_OF_SLAB_CLASSES; i++) { - did_moves += lru_maintainer_juggle(i); + /* Each slab class gets its own sleep to avoid hammering locks */ + for (i = POWER_SMALLEST; i < MAX_NUMBER_OF_SLAB_CLASSES; i++) { + next_juggles[i] = next_juggles[i] > last_sleep ? next_juggles[i] - last_sleep : 0; + + // Sleep the thread just for the minimum amount (or not at all) + if (next_juggles[i] < to_sleep) { + to_sleep = next_juggles[i]; } - } - if (did_moves == 0) { - if (to_sleep < MAX_LRU_MAINTAINER_SLEEP) - to_sleep += 1000; - } else if (to_sleep > 0) { - to_sleep /= 2; - if (to_sleep < MIN_LRU_MAINTAINER_SLEEP) - to_sleep = 0; + if (next_juggles[i] > 0) + continue; + + int did_moves = lru_maintainer_juggle(i); + if (did_moves == 0) { + if (backoff_juggles[i] < MAX_LRU_MAINTAINER_SLEEP) + backoff_juggles[i] += 1000; + } else if (backoff_juggles[i] > 0) { + backoff_juggles[i] /= 2; + if (backoff_juggles[i] < MIN_LRU_MAINTAINER_SLEEP) { + backoff_juggles[i] = 0; + } + } + next_juggles[i] = backoff_juggles[i]; } /* Once per second at most */ if (settings.lru_crawler && last_crawler_check != current_time) { |