Skip to content

Commit

Permalink
compat mode.
Browse files Browse the repository at this point in the history
Enabling the new LRU routine requires starting with `-o lru_maintainer`.

This makes almost all of the tests pass, except refhang.t. Will need new tests
for the LRU maintainer.

So far as I can tell it's still handling the refhang scenario, but in a more
natural way. Instead of flipping the items back to the top of the list, it's
unlinking them from the hash table and LRU. This completely removes them from
the problem, but it doesn't retry as many times to get them out of the way.

A system with many stuck items next to each other could do a handful of OOM's
before clearing the backlog, but it won't keep running into them. The test
appears flaky even in 1.4.22; running with -vv causes it to fail in a funny
way.
  • Loading branch information
dormando committed Jan 7, 2015
1 parent 62415f1 commit d9edfef
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 36 deletions.
86 changes: 55 additions & 31 deletions items.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,19 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags,
* This also gives one fewer code path for a slab alloc/free
*/
for (i = 0; i < 5; i++) {
/* Try to reclaim memory first */
if (!settings.lru_maintainer_thread) {
lru_pull_tail(id, COLD_LRU, 0, false, cur_hv);
}
it = slabs_alloc(ntotal, id, &total_chunks);
if (it == NULL) {
lru_pull_tail(id, HOT_LRU, total_chunks, false, cur_hv);
lru_pull_tail(id, WARM_LRU, total_chunks, false, cur_hv);
lru_pull_tail(id, COLD_LRU, total_chunks, true, cur_hv);
if (settings.lru_maintainer_thread) {
lru_pull_tail(id, HOT_LRU, total_chunks, false, cur_hv);
lru_pull_tail(id, WARM_LRU, total_chunks, false, cur_hv);
lru_pull_tail(id, COLD_LRU, total_chunks, true, cur_hv);
} else {
lru_pull_tail(id, COLD_LRU, 0, true, cur_hv);
}
} else {
break;
}
Expand All @@ -192,7 +200,12 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags,
/* Items are initially loaded into the HOT_LRU. This is '0' but I want at
* least a note here. Compiler (hopefully?) optimizes this out.
*/
id |= HOT_LRU;
if (settings.lru_maintainer_thread) {
id |= HOT_LRU;
} else {
/* There is only COLD in compat-mode */
id |= COLD_LRU;
}
it->slabs_clsid = id;

DEBUG_REFCNT(it, '*');
Expand Down Expand Up @@ -375,10 +388,10 @@ void do_item_update(item *it) {

if ((it->it_flags & ITEM_LINKED) != 0) {
it->time = current_time;
/*
item_unlink_q(it);
item_link_q(it);
*/
if (!settings.lru_maintainer_thread) {
item_unlink_q(it);
item_link_q(it);
}
}
}
}
Expand Down Expand Up @@ -409,9 +422,12 @@ char *item_cachedump(const unsigned int slabs_clsid, const unsigned int limit, u
unsigned int shown = 0;
char key_temp[KEY_MAX_LENGTH + 1];
char temp[512];
unsigned int id = slabs_clsid;
if (!settings.lru_maintainer_thread)
id |= COLD_LRU;

pthread_mutex_lock(&lru_locks[slabs_clsid]);
it = heads[slabs_clsid];
pthread_mutex_lock(&lru_locks[id]);
it = heads[id];

buffer = malloc((size_t)memlimit);
if (buffer == 0) {
Expand Down Expand Up @@ -443,7 +459,7 @@ char *item_cachedump(const unsigned int slabs_clsid, const unsigned int limit, u
bufcurr += 5;

*bytes = bufcurr;
pthread_mutex_unlock(&lru_locks[slabs_clsid]);
pthread_mutex_unlock(&lru_locks[id]);
return buffer;
}

Expand Down Expand Up @@ -496,14 +512,16 @@ void item_stats_totals(ADD_STAT add_stats, void *c) {
(unsigned long long)totals.crawler_reclaimed);
APPEND_STAT("lrutail_reflocked", "%llu",
(unsigned long long)totals.lrutail_reflocked);
APPEND_STAT("moves_to_cold", "%llu",
(unsigned long long)totals.moves_to_cold);
APPEND_STAT("moves_to_warm", "%llu",
(unsigned long long)totals.moves_to_warm);
APPEND_STAT("moves_within_lru", "%llu",
(unsigned long long)totals.moves_within_lru);
APPEND_STAT("direct_reclaims", "%llu",
(unsigned long long)totals.direct_reclaims);
if (settings.lru_maintainer_thread) {
APPEND_STAT("moves_to_cold", "%llu",
(unsigned long long)totals.moves_to_cold);
APPEND_STAT("moves_to_warm", "%llu",
(unsigned long long)totals.moves_to_warm);
APPEND_STAT("moves_within_lru", "%llu",
(unsigned long long)totals.moves_within_lru);
APPEND_STAT("direct_reclaims", "%llu",
(unsigned long long)totals.direct_reclaims);
}
}

void item_stats(ADD_STAT add_stats, void *c) {
Expand All @@ -527,6 +545,7 @@ void item_stats(ADD_STAT add_stats, void *c) {
totals.evicted_nonzero += itemstats[i].evicted_nonzero;
totals.outofmemory += itemstats[i].outofmemory;
totals.tailrepairs += itemstats[i].tailrepairs;
totals.reclaimed += itemstats[i].reclaimed;
totals.expired_unfetched += itemstats[i].expired_unfetched;
totals.evicted_unfetched += itemstats[i].evicted_unfetched;
totals.crawler_reclaimed += itemstats[i].crawler_reclaimed;
Expand All @@ -544,9 +563,11 @@ void item_stats(ADD_STAT add_stats, void *c) {
if (size == 0)
continue;
APPEND_NUM_FMT_STAT(fmt, n, "number", "%u", size);
APPEND_NUM_FMT_STAT(fmt, n, "number_hot", "%u", lru_size_map[0]);
APPEND_NUM_FMT_STAT(fmt, n, "number_warm", "%u", lru_size_map[1]);
APPEND_NUM_FMT_STAT(fmt, n, "number_cold", "%u", lru_size_map[2]);
if (settings.lru_maintainer_thread) {
APPEND_NUM_FMT_STAT(fmt, n, "number_hot", "%u", lru_size_map[0]);
APPEND_NUM_FMT_STAT(fmt, n, "number_warm", "%u", lru_size_map[1]);
APPEND_NUM_FMT_STAT(fmt, n, "number_cold", "%u", lru_size_map[2]);
}
APPEND_NUM_FMT_STAT(fmt, n, "age", "%u", age);
APPEND_NUM_FMT_STAT(fmt, n, "evicted",
"%llu", (unsigned long long)totals.evicted);
Expand All @@ -568,14 +589,16 @@ void item_stats(ADD_STAT add_stats, void *c) {
"%llu", (unsigned long long)totals.crawler_reclaimed);
APPEND_NUM_FMT_STAT(fmt, n, "lrutail_reflocked",
"%llu", (unsigned long long)totals.lrutail_reflocked);
APPEND_NUM_FMT_STAT(fmt, n, "moves_to_cold",
"%llu", (unsigned long long)totals.moves_to_cold);
APPEND_NUM_FMT_STAT(fmt, n, "moves_to_warm",
"%llu", (unsigned long long)totals.moves_to_warm);
APPEND_NUM_FMT_STAT(fmt, n, "moves_within_lru",
"%llu", (unsigned long long)totals.moves_within_lru);
APPEND_NUM_FMT_STAT(fmt, n, "direct_reclaims",
"%llu", (unsigned long long)totals.direct_reclaims);
if (settings.lru_maintainer_thread) {
APPEND_NUM_FMT_STAT(fmt, n, "moves_to_cold",
"%llu", (unsigned long long)totals.moves_to_cold);
APPEND_NUM_FMT_STAT(fmt, n, "moves_to_warm",
"%llu", (unsigned long long)totals.moves_to_warm);
APPEND_NUM_FMT_STAT(fmt, n, "moves_within_lru",
"%llu", (unsigned long long)totals.moves_within_lru);
APPEND_NUM_FMT_STAT(fmt, n, "direct_reclaims",
"%llu", (unsigned long long)totals.direct_reclaims);
}
}

/* getting here means both ascii and binary terminators fit */
Expand Down Expand Up @@ -818,7 +841,8 @@ static int lru_pull_tail(const int orig_id, const int cur_lru,
}
do_item_unlink_nolock(search, hv);
removed++;
} else if ((search->it_flags & ITEM_ACTIVE) != 0) {
} else if ((search->it_flags & ITEM_ACTIVE) != 0
&& settings.lru_maintainer_thread) {
itemstats[id].moves_to_warm++;
search->it_flags &= ~ITEM_ACTIVE;
move_to_lru = WARM_LRU;
Expand Down
15 changes: 10 additions & 5 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ static void settings_init(void) {
settings.lru_crawler = false;
settings.lru_crawler_sleep = 100;
settings.lru_crawler_tocrawl = 0;
settings.lru_maintainer_thread = false;
settings.hashpower_init = 0;
settings.slab_reassign = false;
settings.slab_automove = 0;
Expand Down Expand Up @@ -5075,7 +5076,8 @@ int main (int argc, char **argv) {
HASH_ALGORITHM,
LRU_CRAWLER,
LRU_CRAWLER_SLEEP,
LRU_CRAWLER_TOCRAWL
LRU_CRAWLER_TOCRAWL,
LRU_MAINTAINER
};
char *const subopts_tokens[] = {
[MAXCONNS_FAST] = "maxconns_fast",
Expand All @@ -5087,6 +5089,7 @@ int main (int argc, char **argv) {
[LRU_CRAWLER] = "lru_crawler",
[LRU_CRAWLER_SLEEP] = "lru_crawler_sleep",
[LRU_CRAWLER_TOCRAWL] = "lru_crawler_tocrawl",
[LRU_MAINTAINER] = "lru_maintainer",
NULL
};

Expand Down Expand Up @@ -5415,6 +5418,12 @@ int main (int argc, char **argv) {
}
settings.lru_crawler_tocrawl = tocrawl;
break;
case LRU_MAINTAINER:
if (start_lru_maintainer_thread() != 0) {
fprintf(stderr, "Failed to enable LRU maintainer thread\n");
return 1;
}
break;
default:
printf("Illegal suboption \"%s\"\n", subopts_value);
return 1;
Expand Down Expand Up @@ -5573,10 +5582,6 @@ int main (int argc, char **argv) {
exit(EXIT_FAILURE);
}

if (start_lru_maintainer_thread() == -1) {
exit(EXIT_FAILURE);
}

if (settings.slab_reassign &&
start_slab_maintenance_thread() == -1) {
exit(EXIT_FAILURE);
Expand Down
1 change: 1 addition & 0 deletions t/stats.t
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ my $sock = $server->sock;
## STAT reclaimed 0
## STAT crawler_reclaimed 0
## STAT lrutail_reflocked 0
## see doc/protocol.txt for others
# note that auth stats are tested in auth specfic tests


Expand Down

0 comments on commit d9edfef

Please sign in to comment.