summaryrefslogtreecommitdiff
path: root/items.c
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2017-06-20 17:30:21 -0700
committerdormando <dormando@rydia.net>2017-06-23 01:12:53 -0700
commit5c43b80577a3dcdd47df9221ef42e5af22c1c641 (patch)
tree07589085149f453bf5db0d1cf11072ce98abb471 /items.c
parentdee6557c47e94953d230456569e9ba4974c441d1 (diff)
downloadmemcached-5c43b80577a3dcdd47df9221ef42e5af22c1c641.tar.gz
add a real slab automover algorithm
converts the python script to C, more or less.
Diffstat (limited to 'items.c')
-rw-r--r--items.c70
1 files changed, 59 insertions, 11 deletions
diff --git a/items.c b/items.c
index 8cbb5d4..1ce00da 100644
--- a/items.c
+++ b/items.c
@@ -1,6 +1,7 @@
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "memcached.h"
#include "bipbuffer.h"
+#include "slab_automove.h"
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/resource.h>
@@ -609,6 +610,33 @@ char *item_cachedump(const unsigned int slabs_clsid, const unsigned int limit, u
return buffer;
}
+/* With refactoring of the various stats code the automover won't need a
+ * custom function here.
+ */
+void fill_item_stats_automove(item_stats_automove *am) {
+ int n;
+ for (n = 0; n < MAX_NUMBER_OF_SLAB_CLASSES; n++) {
+ item_stats_automove *cur = &am[n];
+
+ // outofmemory records into HOT
+ int i = n | HOT_LRU;
+ pthread_mutex_lock(&lru_locks[i]);
+ cur->outofmemory = itemstats[i].outofmemory;
+ pthread_mutex_unlock(&lru_locks[i]);
+
+ // evictions and tail age are from COLD
+ i = n | COLD_LRU;
+ pthread_mutex_lock(&lru_locks[i]);
+ cur->evicted = itemstats[i].evicted;
+ if (tails[i]) {
+ cur->age = current_time - tails[i]->time;
+ } else {
+ cur->age = 0;
+ }
+ pthread_mutex_unlock(&lru_locks[i]);
+ }
+}
+
void item_stats_totals(ADD_STAT add_stats, void *c) {
itemstats_t totals;
memset(&totals, 0, sizeof(itemstats_t));
@@ -1293,12 +1321,11 @@ static uint64_t lru_total_bumps_dropped(void) {
static int lru_maintainer_juggle(const int slabs_clsid) {
int i;
int did_moves = 0;
- bool mem_limit_reached = false;
uint64_t total_bytes = 0;
unsigned int chunks_perslab = 0;
- unsigned int chunks_free = 0;
+ //unsigned int chunks_free = 0;
/* TODO: if free_chunks below high watermark, increase aggressiveness */
- chunks_free = slabs_available_chunks(slabs_clsid, &mem_limit_reached,
+ slabs_available_chunks(slabs_clsid, NULL,
&total_bytes, &chunks_perslab);
if (settings.temp_lru) {
/* Only looking for reclaims. Run before we size the LRU. */
@@ -1312,14 +1339,6 @@ static int lru_maintainer_juggle(const int slabs_clsid) {
total_bytes -= temp_lru_size(slabs_clsid);
}
- /* If slab automove is enabled on any level, and we have more than 2 pages
- * worth of chunks free in this class, ask (gently) to reassign a page
- * from this class back into the global pool (0)
- */
- if (settings.slab_automove > 0 && chunks_free > (chunks_perslab * 2.5)) {
- slabs_reassign(slabs_clsid, SLAB_GLOBAL_PAGE_POOL);
- }
-
rel_time_t cold_age = 0;
rel_time_t hot_age = 0;
/* If LRU is in flat mode, force items to drain into COLD via max age */
@@ -1467,6 +1486,7 @@ static void *lru_maintainer_thread(void *arg) {
useconds_t to_sleep = MIN_LRU_MAINTAINER_SLEEP;
useconds_t last_sleep = MIN_LRU_MAINTAINER_SLEEP;
rel_time_t last_crawler_check = 0;
+ rel_time_t last_automove_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;
@@ -1480,6 +1500,10 @@ static void *lru_maintainer_thread(void *arg) {
abort();
}
+ double last_ratio = settings.slab_automove_ratio;
+ void *am = slab_automove_init(settings.slab_automove_window,
+ settings.slab_automove_ratio);
+
pthread_mutex_lock(&lru_maintainer_lock);
if (settings.verbose > 2)
fprintf(stderr, "Starting LRU maintainer background thread\n");
@@ -1537,8 +1561,32 @@ static void *lru_maintainer_thread(void *arg) {
lru_maintainer_crawler_check(&cdata, l);
last_crawler_check = current_time;
}
+
+ if (settings.slab_automove == 1 && last_automove_check != current_time) {
+ if (last_ratio != settings.slab_automove_ratio) {
+ slab_automove_free(am);
+ am = slab_automove_init(settings.slab_automove_window,
+ settings.slab_automove_ratio);
+ last_ratio = settings.slab_automove_ratio;
+ }
+ int src, dst;
+ slab_automove_run(am, &src, &dst);
+ if (src != -1 && dst != -1) {
+ slabs_reassign(src, dst);
+ LOGGER_LOG(l, LOG_SYSEVENTS, LOGGER_SLAB_MOVE, NULL,
+ src, dst);
+ }
+ // dst == 0 means reclaim to global pool, be more aggressive
+ if (dst != 0) {
+ last_automove_check = current_time;
+ } else if (dst == 0) {
+ // also ensure we minimize the thread sleep
+ to_sleep = 1000;
+ }
+ }
}
pthread_mutex_unlock(&lru_maintainer_lock);
+ slab_automove_free(am);
if (settings.verbose > 2)
fprintf(stderr, "LRU maintainer thread stopping\n");