diff --git a/memcached.h b/memcached.h index 2a03bf124..8cb0794cb 100644 --- a/memcached.h +++ b/memcached.h @@ -433,6 +433,7 @@ struct stats_state { uint64_t curr_bytes; uint64_t curr_conns; uint64_t hash_bytes; /* size used for hash tables */ + float extstore_memory_pressure; /* when extstore might memory evict */ unsigned int conn_structs; unsigned int reserved_fds; unsigned int hash_power_level; /* Better hope it's not over 9000 */ diff --git a/slab_automove_extstore.c b/slab_automove_extstore.c index 948d80448..3a766af0c 100644 --- a/slab_automove_extstore.c +++ b/slab_automove_extstore.c @@ -140,6 +140,11 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) { *src = -1; *dst = -1; + // calculate how much memory pressure extstore is under. + // 100% means we need to evict item headers. + unsigned int total_low_pages = 0; + unsigned int total_high_pages = 0; + unsigned int global_count = 0; int global_low = global_pool_check(a, &global_count); // fill after structs @@ -158,6 +163,16 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) { memset(wd, 0, sizeof(struct window_data)); unsigned int free_target = a->sam_after[n].chunks_per_page * MIN_PAGES_FOR_SOURCE; + if (small_slab) { + total_low_pages += a->sam_after[n].total_pages; + } else { + unsigned int pages = a->sam_after[n].total_pages; + // only include potentially movable pages + if (pages > MIN_PAGES_FOR_SOURCE) { + total_high_pages += a->sam_after[n].total_pages; + } + } + // if page delta, oom, or evicted delta, mark window dirty // classes marked dirty cannot donate memory back to global pool. if (a->iam_after[n].evicted - a->iam_before[n].evicted > 0 || @@ -213,6 +228,13 @@ void slab_automove_extstore_run(void *arg, int *src, int *dst) { } } + // update the pressure calculation. + float total_pages = total_low_pages + total_high_pages + global_count; + float memory_pressure = (total_low_pages / total_pages) * 100; + STATS_LOCK(); + stats_state.extstore_memory_pressure = memory_pressure; + STATS_UNLOCK(); + memcpy(a->iam_before, a->iam_after, sizeof(item_stats_automove) * MAX_NUMBER_OF_SLAB_CLASSES); memcpy(a->sam_before, a->sam_after, diff --git a/storage.c b/storage.c index d4f669374..777e0b231 100644 --- a/storage.c +++ b/storage.c @@ -110,6 +110,7 @@ void storage_stats(ADD_STAT add_stats, void *c) { struct extstore_stats st; if (ext_storage) { STATS_LOCK(); + APPEND_STAT("extstore_memory_pressure", "%.2f", stats_state.extstore_memory_pressure); APPEND_STAT("extstore_compact_lost", "%llu", (unsigned long long)stats.extstore_compact_lost); APPEND_STAT("extstore_compact_rescues", "%llu", (unsigned long long)stats.extstore_compact_rescues); APPEND_STAT("extstore_compact_resc_cold", "%llu", (unsigned long long)stats.extstore_compact_resc_cold);