diff options
author | Dustin Sallings <dustin@spy.net> | 2009-03-07 14:39:59 -0800 |
---|---|---|
committer | Dustin Sallings <dustin@spy.net> | 2009-03-07 14:39:59 -0800 |
commit | 15e646258e7d5e7596ebccb351365c66b2ab88a4 (patch) | |
tree | a44d5db07ab5d1dbd676b350d1b2f083481b0877 | |
parent | 3e0307821d0bb937ef76258a2cc9a8abbde717cb (diff) | |
download | memcached-15e646258e7d5e7596ebccb351365c66b2ab88a4.tar.gz |
Added CAS stats.
CAS stats break down into three different types:
* CAS misses (non-existent key)
* CAS hits (key + CAS ID match)
* CAS badval (key + CAS ID mismatch)
hits and bad-val are slab-specific stats. Specifically, they are
both based on the slab ID of the original item (the one being
replaced).
-rw-r--r-- | memcached.c | 31 | ||||
-rw-r--r-- | memcached.h | 3 | ||||
-rw-r--r-- | slabs.c | 14 | ||||
-rwxr-xr-x | t/stats.t | 39 | ||||
-rw-r--r-- | thread.c | 10 |
5 files changed, 95 insertions, 2 deletions
diff --git a/memcached.c b/memcached.c index 18d2078..f209446 100644 --- a/memcached.c +++ b/memcached.c @@ -1868,12 +1868,25 @@ enum store_item_type do_store_item(item *it, int comm, conn *c) { if(old_it == NULL) { // LRU expired stored = NOT_FOUND; + pthread_mutex_lock(&c->thread->stats.mutex); + c->thread->stats.cas_misses++; + pthread_mutex_unlock(&c->thread->stats.mutex); } else if (ITEM_get_cas(it) == ITEM_get_cas(old_it)) { // cas validates + // it and old_it may belong to different classes. + // I'm updating the stats for the one that's getting pushed out + pthread_mutex_lock(&c->thread->stats.mutex); + c->thread->stats.slab_stats[old_it->slabs_clsid].cas_hits++; + pthread_mutex_unlock(&c->thread->stats.mutex); + item_replace(old_it, it); stored = STORED; } else { + pthread_mutex_lock(&c->thread->stats.mutex); + c->thread->stats.slab_stats[old_it->slabs_clsid].cas_badval++; + pthread_mutex_unlock(&c->thread->stats.mutex); + if(settings.verbose > 1) { fprintf(stderr, "CAS: failure: expected %llu, got %llu\n", (unsigned long long)ITEM_get_cas(old_it), @@ -2211,6 +2224,24 @@ static char *server_stats(uint32_t (*add_stats)(char *buf, const char *key, pos += nbytes; *buflen += nbytes; + vlen = sprintf(val, "%llu", (unsigned long long)thread_stats.cas_misses); + nbytes = add_stats(pos, "cas_misses", strlen("cas_misses"), val, vlen, + (void *)c); + pos += nbytes; + *buflen += nbytes; + + vlen = sprintf(val, "%llu", (unsigned long long)slab_stats.cas_hits); + nbytes = add_stats(pos, "cas_hits", strlen("cas_hits"), val, vlen, + (void *)c); + pos += nbytes; + *buflen += nbytes; + + vlen = sprintf(val, "%llu", (unsigned long long)slab_stats.cas_badval); + nbytes = add_stats(pos, "cas_badval", strlen("cas_badval"), val, vlen, + (void *)c); + pos += nbytes; + *buflen += nbytes; + vlen = sprintf(val, "%llu", (unsigned long long)thread_stats.bytes_read); nbytes = add_stats(pos, "bytes_read", strlen("bytes_read"), val, vlen, (void *)c); diff --git a/memcached.h b/memcached.h index 8ccf980..59039ff 100644 --- a/memcached.h +++ b/memcached.h @@ -71,6 +71,8 @@ struct slab_stats { uint64_t set_cmds; uint64_t get_hits; uint64_t delete_hits; + uint64_t cas_hits; + uint64_t cas_badval; uint64_t incr_hits; uint64_t decr_hits; }; @@ -82,6 +84,7 @@ struct thread_stats { uint64_t delete_misses; uint64_t incr_misses; uint64_t decr_misses; + uint64_t cas_misses; uint64_t bytes_read; uint64_t bytes_written; struct slab_stats slab_stats[MAX_NUMBER_OF_SLAB_CLASSES]; @@ -476,6 +476,20 @@ static char *do_slabs_stats(uint32_t (*add_stats)(char *buf, const char *key, linelen += nbytes; bufcurr += nbytes; + sprintf(key, "%d:cas_hits", i); + sprintf(val, "%llu", + (unsigned long long)thread_stats.slab_stats[i].cas_hits); + nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c); + linelen += nbytes; + bufcurr += nbytes; + + sprintf(key, "%d:cas_badval", i); + sprintf(val, "%llu", + (unsigned long long)thread_stats.slab_stats[i].cas_badval); + nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c); + linelen += nbytes; + bufcurr += nbytes; + total++; } } @@ -1,7 +1,7 @@ #!/usr/bin/perl use strict; -use Test::More tests => 51; +use Test::More tests => 70; use FindBin qw($Bin); use lib "$Bin/lib"; use MemcachedTest; @@ -35,6 +35,9 @@ my $sock = $server->sock; ## STAT incr_hits 2 ## STAT decr_misses 1 ## STAT decr_hits 1 +## STAT cas_misses 0 +## STAT cas_hits 0 +## STAT cas_badval 0 ## STAT evictions 0 ## STAT bytes_read 7 ## STAT bytes_written 0 @@ -43,7 +46,7 @@ my $sock = $server->sock; my $stats = mem_stats($sock); # Test number of keys -is(scalar(keys(%$stats)), 28, "28 stats values"); +is(scalar(keys(%$stats)), 31, "31 stats values"); # Test initial state foreach my $key (qw(curr_items total_items bytes cmd_get cmd_set get_hits evictions get_misses bytes_written delete_hits delete_misses incr_hits incr_misses decr_hits decr_misses)) { @@ -110,4 +113,36 @@ print $sock "decr n 1\r\n"; is(scalar <$sock>, "2\r\n", "decr works"); check_incr_stats(1, 1, 1, 1); +# cas stats +sub check_cas_stats { + my ($ch, $cm, $cb) = @_; + my $stats = mem_stats($sock); + + is($stats->{cas_hits}, $ch); + is($stats->{cas_misses}, $cm); + is($stats->{cas_badval}, $cb); +} + +check_cas_stats(0, 0, 0); + +print $sock "cas c 0 0 1 99999999\r\nz\r\n"; +is(scalar <$sock>, "NOT_FOUND\r\n", "missed cas"); +check_cas_stats(0, 1, 0); + +print $sock "set c 0 0 1\r\nx\r\n"; +is(scalar <$sock>, "STORED\r\n", "stored c"); +my ($id, $v) = mem_gets($sock, 'c'); +is('x', $v, 'got the expected value'); + +print $sock "cas c 0 0 1 99999999\r\nz\r\n"; +is(scalar <$sock>, "EXISTS\r\n", "missed cas"); +check_cas_stats(0, 1, 1); +my ($newid, $v) = mem_gets($sock, 'c'); +is('x', $v, 'got the expected value'); + +print $sock "cas c 0 0 1 $id\r\nz\r\n"; +is(scalar <$sock>, "STORED\r\n", "good cas"); +check_cas_stats(1, 1, 1); +my ($newid, $v) = mem_gets($sock, 'c'); +is('z', $v, 'got the expected value'); @@ -562,6 +562,7 @@ void threadlocal_stats_aggregate(struct thread_stats *stats) { stats->delete_misses = 0; stats->incr_misses = 0; stats->decr_misses = 0; + stats->cas_misses = 0; stats->bytes_written = 0; stats->bytes_read = 0; @@ -576,6 +577,7 @@ void threadlocal_stats_aggregate(struct thread_stats *stats) { stats->delete_misses += threads[ii].stats.delete_misses; stats->decr_misses += threads[ii].stats.decr_misses; stats->incr_misses += threads[ii].stats.incr_misses; + stats->cas_misses += threads[ii].stats.cas_misses; stats->bytes_read += threads[ii].stats.bytes_read; stats->bytes_written += threads[ii].stats.bytes_written; @@ -590,6 +592,10 @@ void threadlocal_stats_aggregate(struct thread_stats *stats) { threads[ii].stats.slab_stats[sid].decr_hits; stats->slab_stats[sid].incr_hits += threads[ii].stats.slab_stats[sid].incr_hits; + stats->slab_stats[sid].cas_hits += + threads[ii].stats.slab_stats[sid].cas_hits; + stats->slab_stats[sid].cas_badval += + threads[ii].stats.slab_stats[sid].cas_badval; } pthread_mutex_unlock(&threads[ii].stats.mutex); @@ -604,6 +610,8 @@ void slab_stats_aggregate(struct thread_stats *stats, struct slab_stats *out) { out->delete_hits = 0; out->incr_hits = 0; out->decr_hits = 0; + out->cas_hits = 0; + out->cas_badval = 0; for (sid = 0; sid < MAX_NUMBER_OF_SLAB_CLASSES; sid++) { out->set_cmds += stats->slab_stats[sid].set_cmds; @@ -611,6 +619,8 @@ void slab_stats_aggregate(struct thread_stats *stats, struct slab_stats *out) { out->delete_hits += stats->slab_stats[sid].delete_hits; out->decr_hits += stats->slab_stats[sid].decr_hits; out->incr_hits += stats->slab_stats[sid].incr_hits; + out->cas_hits += stats->slab_stats[sid].cas_hits; + out->cas_badval += stats->slab_stats[sid].cas_badval; } } |