Skip to content

Commit

Permalink
LRU maintainer performance: per-class sleep
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dormando committed Jan 23, 2017
1 parent fa8b425 commit 2266c84
Showing 1 changed file with 28 additions and 18 deletions.
46 changes: 28 additions & 18 deletions items.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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) {
Expand Down

0 comments on commit 2266c84

Please sign in to comment.