diff options
author | dormando <dormando@rydia.net> | 2017-11-28 17:56:20 -0800 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2017-11-28 17:56:20 -0800 |
commit | 81c83e803d2be797f70147e7214b2382ecadb5fc (patch) | |
tree | 54a625358371781fbbc26ac8871d960b6f0b682a | |
parent | 9716994daec8b30844c5c9bb8ee69f2dba031929 (diff) | |
download | memcached-81c83e803d2be797f70147e7214b2382ecadb5fc.tar.gz |
extstore: add ext_drop_unread option + live tune
was struggling to figure out how to automatically turn this on or off, but I
think it should be part of an outside process.
ie; a mechanism should be able to target a specific write rate, and one of
its tools for reducing the write rate should be flipping this on.
there's *still* a hole where you can't trigger a compaction attempt if
there's no fragmentation. I kind of want, if this feature is on, to attempt
a compaction on the oldest page while dropping unread items.
-rw-r--r-- | memcached.c | 14 | ||||
-rw-r--r-- | memcached.h | 1 | ||||
-rw-r--r-- | storage.c | 11 | ||||
-rw-r--r-- | t/extstore.t | 9 |
4 files changed, 28 insertions, 7 deletions
diff --git a/memcached.c b/memcached.c index 1c4e8bf..a93f87d 100644 --- a/memcached.c +++ b/memcached.c @@ -4487,6 +4487,13 @@ static void process_extstore_command(conn *c, token_t *tokens, const size_t ntok } else if (strcmp(tokens[1].value, "max_frag") == 0) { if (!safe_strtod(tokens[2].value, &settings.ext_max_frag)) ok = false; + } else if (strcmp(tokens[1].value, "drop_unread") == 0) { + unsigned int v; + if (!safe_strtoul(tokens[2].value, &v)) { + ok = false; + } else { + settings.ext_drop_unread = v == 0 ? false : true; + } } else { ok = false; } @@ -6161,6 +6168,7 @@ static void usage(void) { " - ext_item_size: store items larger than this (bytes)\n" " - ext_item_age: store items idle at least this long\n" " - ext_low_ttl: consider TTLs lower than this specially\n" + " - ext_drop_unread: don't re-write unread values during compaction\n" " - ext_recache_rate: recache an item every N accesses\n" " - ext_max_frag: max page fragmentation to tolerage\n" " (see doc/storage.txt for more info)" @@ -6499,6 +6507,7 @@ int main (int argc, char **argv) { EXT_LOW_TTL, EXT_RECACHE_RATE, EXT_MAX_FRAG, + EXT_DROP_UNREAD, #endif }; char *const subopts_tokens[] = { @@ -6553,6 +6562,7 @@ int main (int argc, char **argv) { [EXT_LOW_TTL] = "ext_low_ttl", [EXT_RECACHE_RATE] = "ext_recache_rate", [EXT_MAX_FRAG] = "ext_max_frag", + [EXT_DROP_UNREAD] = "ext_drop_unread", #endif NULL }; @@ -6573,6 +6583,7 @@ int main (int argc, char **argv) { settings.ext_low_ttl = 0; settings.ext_recache_rate = 2000; settings.ext_max_frag = 0.8; + settings.ext_drop_unread = false; settings.ext_wbuf_size = 1024 * 1024 * 4; ext_cf.page_size = 1024 * 1024 * 64; ext_cf.page_count = 64; @@ -7221,6 +7232,9 @@ int main (int argc, char **argv) { return 1; } break; + case EXT_DROP_UNREAD: + settings.ext_drop_unread = true; + break; case EXT_PATH: storage_file = strdup(subopts_value); break; diff --git a/memcached.h b/memcached.h index 5a6cec8..dff66a2 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 */ double ext_max_frag; /* ideal maximum page fragmentation */ + bool ext_drop_unread; /* skip unread items during compaction */ #endif }; @@ -130,7 +130,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, bool *drop_unread) { + uint64_t *page_size) { struct extstore_stats st; int x; double rate; @@ -148,10 +148,6 @@ static int storage_compact_check(void *storage, logger *l, // the number of free pages reduces the configured frag limit // this allows us to defrag early if pages are very empty. rate = 1.0 - ((double)st.pages_free / st.page_count); - // if we're nearly out of pages, drop more data ahead of eviction. - if (st.pages_free < 2) { - *drop_unread = true; - } rate *= settings.ext_max_frag; frag_limit = st.page_size * rate; LOGGER_LOG(l, LOG_SYSEVENTS, LOGGER_COMPACT_FRAGINFO, @@ -348,9 +344,11 @@ 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, &drop_unread)) { + &page_id, &page_version, &page_size)) { 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); } @@ -385,7 +383,6 @@ static void *storage_compact_thread(void *arg) { compacting = false; wrap.done = false; wrap.submitted = false; - drop_unread = false; extstore_close_page(storage, page_id, page_version); LOGGER_LOG(l, LOG_SYSEVENTS, LOGGER_COMPACT_END, NULL, page_id); diff --git a/t/extstore.t b/t/extstore.t index 8a8180e..4963ca6 100644 --- a/t/extstore.t +++ b/t/extstore.t @@ -100,6 +100,13 @@ mem_get_is($sock, "foo", "hi"); is($stats->{extstore_pages_free}, 0, '0 pages are free'); is($stats->{miss_from_extstore}, 1, 'exactly one miss'); + # refresh some keys so rescues happen while drop_unread == 1. + for (1 .. $keycount / 2) { + next unless $_ % 2 == 1; + print $sock "touch mfoo$_ 0 noreply\r\n"; + } + print $sock "extstore drop_unread 1\r\n"; + my $res = <$sock>; for (1 .. $keycount) { next unless $_ % 2 == 0; print $sock "delete mfoo$_ noreply\r\n"; @@ -110,6 +117,8 @@ mem_get_is($sock, "foo", "hi"); cmp_ok($stats->{extstore_pages_free}, '>', 0, 'some pages now free'); cmp_ok($stats->{extstore_compact_rescues}, '>', 0, 'some compaction rescues happened'); cmp_ok($stats->{extstore_compact_skipped}, '>', 0, 'some compaction skips happened'); + print $sock "extstore drop_unread 0\r\n"; + $res = <$sock>; } # attempt to incr/decr/append/prepend or chunk objects that were sent to disk. |