summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--memcached.c19
-rw-r--r--memcached.h1
-rw-r--r--storage.c11
-rw-r--r--t/extstore.t2
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 */
diff --git a/storage.c b/storage.c
index 2f378bf..648ef35 100644
--- a/storage.c
+++ b/storage.c
@@ -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";