summaryrefslogtreecommitdiff
path: root/items.c
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2017-01-08 16:55:16 -0800
committerdormando <dormando@rydia.net>2017-01-22 19:57:15 -0800
commit2266c8402bd4f8a2f2a2da6a053c1d63a628e230 (patch)
treeea7c7a795d2da86906b95a7de4e8ca4be676dc03 /items.c
parentfa8b42560aa948822514ed6560d8448623049297 (diff)
downloadmemcached-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.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/items.c b/items.c
index be83200..e236fcf 100644
--- a/items.c
+++ b/items.c
@@ -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) {