From 839949a9951bf54917eab8c6c1c5b2b8e2468e17 Mon Sep 17 00:00:00 2001 From: dormando Date: Wed, 28 Sep 2011 17:04:48 -0700 Subject: Add new stats expired_unfetched, evicted_unfetched The two stats represent items which expired and memory was reused, and valid items which were evicted, but never touched by get/incr/append/etc operations in the meantime. Useful for seeing how many wasted items are being set and then rolling out through the bottom of the LRU's. --- doc/protocol.txt | 11 ++++++++++- items.c | 29 +++++++++++++++++++++++++++-- memcached.c | 5 ++++- memcached.h | 4 ++++ t/binary.t | 2 +- t/stats.t | 2 +- 6 files changed, 47 insertions(+), 6 deletions(-) diff --git a/doc/protocol.txt b/doc/protocol.txt index 16a87eb..5337d48 100644 --- a/doc/protocol.txt +++ b/doc/protocol.txt @@ -449,7 +449,12 @@ integers separated by a colon (treat this as a floating point number). | hash_power_level | 32u | Current size multiplier for hash table | | hash_bytes | 64u | Bytes currently used by hash tables | | hash_is_expanding | bool | Indicates if the hash table is being | -| | | grown to a new size +| | | grown to a new size | +| expired_unfetched | 64u | Items pulled from LRU that were never | +| | | touched by get/incr/append/etc before | +| | | expiring | +| evicted_unfetched | 64u | Items evicted from LRU that were never | +| | | touched by get/incr/append/etc. | |-----------------------+---------+-------------------------------------------| Settings statistics @@ -531,6 +536,10 @@ tailrepairs Number of times we self-healed a slab with a refcount report your situation to the developers. reclaimed Number of times an entry was stored using memory from an expired entry. +expired_unfetched Number of expired items reclaimed from the LRU which + were never touched after being set. +evicted_unfetched Number of valid items evicted from the LRU which were + never touched after being set. Note this will only display information about slabs which exist, so an empty cache will return an empty set. diff --git a/items.c b/items.c index 288cdb8..afa9e1c 100644 --- a/items.c +++ b/items.c @@ -32,6 +32,8 @@ typedef struct { unsigned int reclaimed; unsigned int outofmemory; unsigned int tailrepairs; + unsigned int expired_unfetched; + unsigned int evicted_unfetched; } itemstats_t; static item *heads[LARGEST_ID]; @@ -115,6 +117,12 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim stats.reclaimed++; STATS_UNLOCK(); itemstats[id].reclaimed++; + if ((it->it_flags & ITEM_FETCHED) == 0) { + STATS_LOCK(); + stats.expired_unfetched++; + STATS_UNLOCK(); + itemstats[id].expired_unfetched++; + } it->refcount = 1; slabs_adjust_mem_requested(it->slabs_clsid, ITEM_ntotal(it), ntotal); do_item_unlink(it); @@ -160,6 +168,12 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim itemstats[id].evicted_time = current_time - search->time; if (search->exptime != 0) itemstats[id].evicted_nonzero++; + if ((search->it_flags & ITEM_FETCHED) == 0) { + STATS_LOCK(); + stats.evicted_unfetched++; + STATS_UNLOCK(); + itemstats[id].evicted_unfetched++; + } STATS_LOCK(); stats.evictions++; STATS_UNLOCK(); @@ -168,6 +182,12 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim STATS_LOCK(); stats.reclaimed++; STATS_UNLOCK(); + if ((search->it_flags & ITEM_FETCHED) == 0) { + STATS_LOCK(); + stats.expired_unfetched++; + STATS_UNLOCK(); + itemstats[id].expired_unfetched++; + } } do_item_unlink(search); break; @@ -439,9 +459,13 @@ void do_item_stats(ADD_STAT add_stats, void *c) { APPEND_NUM_FMT_STAT(fmt, i, "outofmemory", "%u", itemstats[i].outofmemory); APPEND_NUM_FMT_STAT(fmt, i, "tailrepairs", - "%u", itemstats[i].tailrepairs);; + "%u", itemstats[i].tailrepairs); APPEND_NUM_FMT_STAT(fmt, i, "reclaimed", - "%u", itemstats[i].reclaimed);; + "%u", itemstats[i].reclaimed); + APPEND_NUM_FMT_STAT(fmt, i, "expired_unfetched", + "%u", itemstats[i].expired_unfetched); + APPEND_NUM_FMT_STAT(fmt, i, "evicted_unfetched", + "%u", itemstats[i].evicted_unfetched); } } @@ -522,6 +546,7 @@ item *do_item_get(const char *key, const size_t nkey) { if (it != NULL) { it->refcount++; + it->it_flags |= ITEM_FETCHED; DEBUG_REFCNT(it, '+'); } diff --git a/memcached.c b/memcached.c index a548eb2..c7df0bd 100644 --- a/memcached.c +++ b/memcached.c @@ -169,6 +169,7 @@ static void stats_init(void) { stats.touch_cmds = stats.touch_misses = stats.touch_hits = stats.rejected_conns = 0; stats.curr_bytes = stats.listen_disabled_num = 0; stats.hash_power_level = stats.hash_bytes = stats.hash_is_expanding = 0; + stats.expired_unfetched = stats.evicted_unfetched = 0; stats.accepting_conns = true; /* assuming we start in this state. */ /* make the time we started always be 2 seconds before we really @@ -2561,6 +2562,8 @@ static void server_stats(ADD_STAT add_stats, conn *c) { APPEND_STAT("hash_power_level", "%u", stats.hash_power_level); APPEND_STAT("hash_bytes", "%llu", (unsigned long long)stats.hash_bytes); APPEND_STAT("hash_is_expanding", "%u", stats.hash_is_expanding); + APPEND_STAT("expired_unfetched", "%llu", stats.expired_unfetched); + APPEND_STAT("evicted_unfetched", "%llu", stats.evicted_unfetched); STATS_UNLOCK(); } @@ -4869,7 +4872,7 @@ int main (int argc, char **argv) { fprintf(stderr, "Initial hashtable multiplier of %d is too high\n" "Choose a value based on \"STAT hash_power_level\" from a running instance\n", settings.hashpower_init); - return 1; + return 1; } break; default: diff --git a/memcached.h b/memcached.h index 8fe9113..c75ef46 100644 --- a/memcached.h +++ b/memcached.h @@ -263,6 +263,8 @@ struct stats { unsigned int hash_power_level; /* Better hope it's not over 9000 */ uint64_t hash_bytes; /* size used for hash tables */ bool hash_is_expanding; /* If the hash table is being expanded */ + uint64_t expired_unfetched; /* items reclaimed but never touched */ + uint64_t evicted_unfetched; /* items evicted but never touched */ }; #define MAX_VERBOSITY_LEVEL 2 @@ -309,6 +311,8 @@ extern struct settings settings; /* temp */ #define ITEM_SLABBED 4 +#define ITEM_FETCHED 8 + /** * Structure for storing items within memcached. */ diff --git a/t/binary.t b/t/binary.t index 99dcc52..85ed46f 100755 --- a/t/binary.t +++ b/t/binary.t @@ -2,7 +2,7 @@ use strict; use warnings; -use Test::More tests => 3470; +use Test::More tests => 3533; use FindBin qw($Bin); use lib "$Bin/lib"; use MemcachedTest; diff --git a/t/stats.t b/t/stats.t index 7c78617..97a5b7c 100755 --- a/t/stats.t +++ b/t/stats.t @@ -58,7 +58,7 @@ my $sock = $server->sock; my $stats = mem_stats($sock); # Test number of keys -is(scalar(keys(%$stats)), 43, "43 stats values"); +is(scalar(keys(%$stats)), 48, "48 stats values"); # Test initial state foreach my $key (qw(curr_items total_items bytes cmd_get cmd_set get_hits evictions get_misses -- cgit v1.2.1