diff options
author | dormando <dormando@rydia.net> | 2017-12-15 15:06:24 -0800 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2017-12-15 15:06:24 -0800 |
commit | b6f7b55eea7dba509292c8d88ede43e1dd592259 (patch) | |
tree | b83c1227aaed30aa44a8ed48fed4d4e51264db69 | |
parent | a78d168f6d82c8b6e073dc8c89b80e988eafe657 (diff) | |
download | memcached-b6f7b55eea7dba509292c8d88ede43e1dd592259.tar.gz |
extstore: tuning drop_unread semantics
there's now an optional ext_drop_under setting which defaults to the same as
compact_under, which should be fine. now, if drop_unread is enabled, it only
kicks in if there are no pages matching the compaction threshold.
This allows you to set a lower compaction frag rate, then start rescuing only
non-COLD items if storage is too full. You can also compact up to a point,
then allow a buffer of pages to be used before dropping unread.
previously enabling drop_unread would always drop_unread even when compacting
normally. This limited utility of the feature.
-rw-r--r-- | memcached.c | 19 | ||||
-rw-r--r-- | memcached.h | 1 | ||||
-rw-r--r-- | storage.c | 11 | ||||
-rw-r--r-- | t/extstore.t | 2 |
4 files changed, 28 insertions, 5 deletions
diff --git a/memcached.c b/memcached.c index 1f1ff92..0447bf2 100644 --- a/memcached.c +++ b/memcached.c @@ -4534,6 +4534,9 @@ static void process_extstore_command(conn *c, token_t *tokens, const size_t ntok } else if (strcmp(tokens[1].value, "compact_under") == 0) { if (!safe_strtoul(tokens[2].value, &settings.ext_compact_under)) ok = false; + } else if (strcmp(tokens[1].value, "drop_under") == 0) { + if (!safe_strtoul(tokens[2].value, &settings.ext_drop_under)) + ok = false; } else if (strcmp(tokens[1].value, "max_frag") == 0) { if (!safe_strtod(tokens[2].value, &settings.ext_max_frag)) ok = false; @@ -6221,6 +6224,7 @@ static void usage(void) { " - ext_drop_unread: don't re-write unread values during compaction\n" " - ext_recache_rate: recache an item every N accesses\n" " - ext_compact_under: compact when fewer than this many free pages\n" + " - ext_drop_under: drop COLD items when fewer than this many free pages\n" " - ext_max_frag: max page fragmentation to tolerage\n" " (see doc/storage.txt for more info)" #endif @@ -6558,6 +6562,7 @@ int main (int argc, char **argv) { EXT_LOW_TTL, EXT_RECACHE_RATE, EXT_COMPACT_UNDER, + EXT_DROP_UNDER, EXT_MAX_FRAG, EXT_DROP_UNREAD, #endif @@ -6614,6 +6619,7 @@ int main (int argc, char **argv) { [EXT_LOW_TTL] = "ext_low_ttl", [EXT_RECACHE_RATE] = "ext_recache_rate", [EXT_COMPACT_UNDER] = "ext_compact_under", + [EXT_DROP_UNDER] = "ext_drop_under", [EXT_MAX_FRAG] = "ext_max_frag", [EXT_DROP_UNREAD] = "ext_drop_unread", #endif @@ -6639,6 +6645,7 @@ int main (int argc, char **argv) { settings.ext_drop_unread = false; settings.ext_wbuf_size = 1024 * 1024 * 4; settings.ext_compact_under = 0; + settings.ext_drop_under = 0; settings.slab_automove_freeratio = 0.005; ext_cf.page_size = 1024 * 1024 * 64; ext_cf.page_count = 64; @@ -7269,6 +7276,16 @@ int main (int argc, char **argv) { return 1; } break; + case EXT_DROP_UNDER: + if (subopts_value == NULL) { + fprintf(stderr, "Missing ext_drop_under argument\n"); + return 1; + } + if (!safe_strtoul(subopts_value, &settings.ext_drop_under)) { + fprintf(stderr, "could not parse argument to ext_drop_under\n"); + return 1; + } + break; case EXT_MAX_FRAG: if (subopts_value == NULL) { fprintf(stderr, "Missing ext_max_frag argument\n"); @@ -7542,6 +7559,8 @@ int main (int argc, char **argv) { if (storage_file) { if (settings.ext_compact_under == 0) { settings.ext_compact_under = ext_cf.page_count / 4; + /* Only rescues non-COLD items if below this threshold */ + settings.ext_drop_under = ext_cf.page_count / 4; } crc32c_init(); /* Keep at least one chunk free by default. */ diff --git a/memcached.h b/memcached.h index 98c45d7..22893f5 100644 --- a/memcached.h +++ b/memcached.h @@ -412,6 +412,7 @@ struct settings { unsigned int ext_recache_rate; /* counter++ % recache_rate == 0 > recache */ unsigned int ext_wbuf_size; /* read only note for the engine */ unsigned int ext_compact_under; /* when fewer than this many pages, compact */ + unsigned int ext_drop_under; /* when fewer than this many pages, drop COLD items */ double ext_max_frag; /* ideal maximum page fragmentation */ double slab_automove_freeratio; /* % of memory to hold free as buffer */ bool ext_drop_unread; /* skip unread items during compaction */ @@ -131,7 +131,7 @@ int lru_maintainer_store(void *storage, const int clsid) { */ static int storage_compact_check(void *storage, logger *l, uint32_t *page_id, uint64_t *page_version, - uint64_t *page_size) { + uint64_t *page_size, bool *drop_unread) { struct extstore_stats st; int x; double rate; @@ -147,6 +147,7 @@ static int storage_compact_check(void *storage, logger *l, // lets pick a target "wasted" value and slew. if (st.pages_free > settings.ext_compact_under) return 0; + *drop_unread = false; // the number of free pages reduces the configured frag limit // this allows us to defrag early if pages are very empty. @@ -182,11 +183,13 @@ static int storage_compact_check(void *storage, logger *l, *page_id = low_page; *page_version = low_version; return 1; - } else if (lowest_version != ULLONG_MAX && settings.ext_drop_unread) { + } else if (lowest_version != ULLONG_MAX && settings.ext_drop_unread + && st.pages_free <= settings.ext_drop_under) { // nothing matched the frag rate barrier, so pick the absolute oldest // version if we're configured to drop items. *page_id = lowest_page; *page_version = lowest_version; + *drop_unread = true; return 1; } @@ -358,11 +361,9 @@ static void *storage_compact_thread(void *arg) { pthread_mutex_lock(&storage_compact_plock); if (!compacting && storage_compact_check(storage, l, - &page_id, &page_version, &page_size)) { + &page_id, &page_version, &page_size, &drop_unread)) { page_offset = 0; compacting = true; - // only allow this to flip inbetween compactions. - drop_unread = settings.ext_drop_unread; LOGGER_LOG(l, LOG_SYSEVENTS, LOGGER_COMPACT_START, NULL, page_id, page_version); } diff --git a/t/extstore.t b/t/extstore.t index f80c4e5..df4ca05 100644 --- a/t/extstore.t +++ b/t/extstore.t @@ -109,6 +109,8 @@ mem_get_is($sock, "foo", "hi"); } print $sock "extstore drop_unread 1\r\n"; my $res = <$sock>; + print $sock "extstore max_frag 0\r\n"; + $res = <$sock>; for (1 .. $keycount) { next unless $_ % 2 == 0; print $sock "delete mfoo$_ noreply\r\n"; |