summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2011-09-28 17:04:48 -0700
committerdormando <dormando@rydia.net>2011-09-28 17:04:48 -0700
commit839949a9951bf54917eab8c6c1c5b2b8e2468e17 (patch)
tree19822422f3169af007aa4af3dfc871107cb75365
parent1db1de38283fdd3f5cdc556ac9ca9cb05892a75d (diff)
downloadmemcached-839949a9951bf54917eab8c6c1c5b2b8e2468e17.tar.gz
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.
-rw-r--r--doc/protocol.txt11
-rw-r--r--items.c29
-rw-r--r--memcached.c5
-rw-r--r--memcached.h4
-rwxr-xr-xt/binary.t2
-rwxr-xr-xt/stats.t2
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