Skip to content

Commit

Permalink
Merge commit '366108d785ceccb36bb9d171f53c873cea457c5b' into binary
Browse files Browse the repository at this point in the history
* commit '366108d785ceccb36bb9d171f53c873cea457c5b':
  Halve distro size ;)
  Add -L mode to manpage.
  Version bump (shipit's having trouble with it), and update ChangeLog
  per-stat-class tracking of evictions and out of memory conditions.
  Don't re-calculate the slab class id for slabs_free() either.
  Don't re-calculate the slab class id.
  Useless check. 'id' will never be higher than POWER_LARGEST.
  Give 'SERVER_ERROR out of memory' errors more context.
  Minor refactoring of server_socket.

Conflicts:

	memcached.c
  • Loading branch information
dustin committed Apr 27, 2008
2 parents 471ae12 + 4fb7ccd commit 733db22
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 41 deletions.
14 changes: 14 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
2008-03-02 [Version 1.2.5-rc1 released]

* Add per-item-class tracking of evictions and OOM errors (dormando)

* Optimize item_alloc() a little (dormando)

* Give 'SERVER_ERROR out of memory' errors more context (dormando)

* Enable usage of large memory pages under solaris
(Trond.Norbye@Sun.COM)

* Enable UDP by default, clean up server socket code
(brian@tangent.org)

* 'noreply' support (Tomash Brechko)

* IPv6 support, and IPv6 multi-interface support (brian@tangent.org)
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
AC_PREREQ(2.52)
AC_INIT(memcached, 1.2.4, brad@danga.com)
AC_INIT(memcached, 1.2.5, brad@danga.com)
AC_CANONICAL_SYSTEM
AC_CONFIG_SRCDIR(memcached.c)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
Expand Down
Binary file removed doc/binary-protocol-plan.jpg
Binary file not shown.
6 changes: 6 additions & 0 deletions doc/memcached.1
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ Use <char> as the delimiter between key prefixes and IDs. This is used for
per-prefix stats reporting. The default is ":" (colon). If this option is
specified, stats collection is turned on automatically; if not, then it may
be turned on by sending the "stats detail on" command to the server.
.TP
.B \-L
Try to use large memory pages (if available). Increasing the memory page size
could reduce the number of TLB misses and improve the performance. In order to
get large pages from the OS, memcached will allocate the total item-cache in
one large chunk. Only available if supported on your OS.
.br
.SH LICENSE
The memcached daemon is copyright Danga Interactive and is distributed under
Expand Down
51 changes: 37 additions & 14 deletions items.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,19 @@ static uint64_t get_cas_id();
#define ITEM_UPDATE_INTERVAL 60

#define LARGEST_ID 255
typedef struct {
unsigned int evicted;
unsigned int outofmemory;
} itemstats_t;

static item *heads[LARGEST_ID];
static item *tails[LARGEST_ID];
static itemstats_t itemstats[LARGEST_ID];
static unsigned int sizes[LARGEST_ID];

void item_init(void) {
int i;
memset(itemstats, 0, sizeof(itemstats_t) * LARGEST_ID);
for(i = 0; i < LARGEST_ID; i++) {
heads[i] = NULL;
tails[i] = NULL;
Expand Down Expand Up @@ -88,7 +95,7 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
if (id == 0)
return 0;

it = slabs_alloc(ntotal);
it = slabs_alloc(ntotal, id);
if (it == 0) {
int tries = 50;
item *search;
Expand All @@ -97,7 +104,10 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
* we're out of luck at this point...
*/

if (settings.evict_to_free == 0) return NULL;
if (settings.evict_to_free == 0) {
itemstats[id].outofmemory++;
return NULL;
}

/*
* try to get one off the right LRU
Expand All @@ -106,22 +116,28 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim
* tries
*/

if (id > LARGEST_ID) return NULL;
if (tails[id] == 0) return NULL;
if (tails[id] == 0) {
itemstats[id].outofmemory++;
return NULL;
}

for (search = tails[id]; tries > 0 && search != NULL; tries--, search=search->prev) {
if (search->refcount == 0) {
if (search->exptime == 0 || search->exptime > current_time) {
STATS_LOCK();
stats.evictions++;
STATS_UNLOCK();
if (search->exptime == 0 || search->exptime > current_time) {
itemstats[id].evicted++;
STATS_LOCK();
stats.evictions++;
STATS_UNLOCK();
}
do_item_unlink(search);
break;
}
}
it = slabs_alloc(ntotal);
if (it == 0) return NULL;
it = slabs_alloc(ntotal, id);
if (it == 0) {
itemstats[id].outofmemory++;
return NULL;
}
}

assert(it->slabs_clsid == 0);
Expand All @@ -145,16 +161,18 @@ item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_tim

void item_free(item *it) {
size_t ntotal = ITEM_ntotal(it);
unsigned int clsid;
assert((it->it_flags & ITEM_LINKED) == 0);
assert(it != heads[it->slabs_clsid]);
assert(it != tails[it->slabs_clsid]);
assert(it->refcount == 0);

/* so slab size changer can tell later if item is already free or not */
clsid = it->slabs_clsid;
it->slabs_clsid = 0;
it->it_flags |= ITEM_SLABBED;
DEBUG_REFCNT(it, 'F');
slabs_free(it, ntotal);
slabs_free(it, ntotal, clsid);
}

/**
Expand Down Expand Up @@ -310,7 +328,7 @@ char *do_item_cachedump(const unsigned int slabs_clsid, const unsigned int limit
}

char *do_item_stats(int *bytes) {
size_t bufleft = (size_t) LARGEST_ID * 80;
size_t bufleft = (size_t) LARGEST_ID * 160;
char *buffer = malloc(bufleft);
char *bufcurr = buffer;
rel_time_t now = current_time;
Expand All @@ -323,8 +341,13 @@ char *do_item_stats(int *bytes) {

for (i = 0; i < LARGEST_ID; i++) {
if (tails[i] != NULL) {
linelen = snprintf(bufcurr, bufleft, "STAT items:%d:number %u\r\nSTAT items:%d:age %u\r\n",
i, sizes[i], i, now - tails[i]->time);
linelen = snprintf(bufcurr, bufleft,
"STAT items:%d:number %u\r\n"
"STAT items:%d:age %u\r\n"
"STAT items:%d:evicted %u\r\n"
"STAT items:%d:outofmemory %u\r\n",
i, sizes[i], i, now - tails[i]->time, i,
itemstats[i].evicted, i, itemstats[i].outofmemory);
if (linelen + sizeof("END\r\n") < bufleft) {
bufcurr += linelen;
bufleft -= linelen;
Expand Down
18 changes: 9 additions & 9 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -1612,7 +1612,7 @@ static void write_and_free(conn *c, char *buf, int bytes) {
conn_set_state(c, conn_write);
c->write_and_go = get_init_state(c);
} else {
out_string(c, "SERVER_ERROR out of memory");
out_string(c, "SERVER_ERROR out of memory writing stats");
}
}

Expand Down Expand Up @@ -1749,7 +1749,7 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
int res;

if ((wbuf = (char *)malloc(wsize)) == NULL) {
out_string(c, "SERVER_ERROR out of memory");
out_string(c, "SERVER_ERROR out of memory writing stats maps");
return;
}

Expand Down Expand Up @@ -1916,7 +1916,7 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens,
stats.get_hits += stats_get_hits;
stats.get_misses += stats_get_misses;
STATS_UNLOCK();
out_string(c, "SERVER_ERROR out of memory");
out_string(c, "SERVER_ERROR out of memory making CAS suffix");
return;
}
*(c->suffixlist + i) = suffix;
Expand Down Expand Up @@ -1985,7 +1985,7 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens,
*/
if (key_token->value != NULL || add_iov(c, "END\r\n", 5) != 0
|| (IS_UDP(c->protocol) && build_udp_headers(c) != 0)) {
out_string(c, "SERVER_ERROR out of memory");
out_string(c, "SERVER_ERROR out of memory writing get response");
}
else {
conn_set_state(c, conn_mwrite);
Expand Down Expand Up @@ -2060,7 +2060,7 @@ static void process_update_command(conn *c, token_t *tokens, const size_t ntoken
if (! item_size_ok(nkey, flags, vlen + 2))
out_string(c, "SERVER_ERROR object too large for cache");
else
out_string(c, "SERVER_ERROR out of memory");
out_string(c, "SERVER_ERROR out of memory storing object");
/* swallow the data line */
c->write_and_go = conn_swallow;
c->sbytes = vlen + 2;
Expand Down Expand Up @@ -2163,7 +2163,7 @@ char *do_add_delta(item *it, const bool incr, const int64_t delta, char *buf) {
item *new_it;
new_it = do_item_alloc(ITEM_key(it), it->nkey, atoi(ITEM_suffix(it) + 1), it->exptime, res + 2 );
if (new_it == 0) {
return "SERVER_ERROR out of memory";
return "SERVER_ERROR out of memory in incr/decr";
}
memcpy(ITEM_data(new_it), buf, res);
memcpy(ITEM_data(new_it) + res, "\r\n", 3);
Expand Down Expand Up @@ -2254,7 +2254,7 @@ char *do_defer_delete(item *it, time_t exptime)
* but we ran out of memory for the delete queue
*/
item_remove(it); /* release reference */
return "SERVER_ERROR out of memory";
return "SERVER_ERROR out of memory expanding delete queue";
}
}

Expand Down Expand Up @@ -2299,7 +2299,7 @@ static void process_command(conn *c, char *command) {
c->msgused = 0;
c->iovused = 0;
if (add_msghdr(c) != 0) {
out_string(c, "SERVER_ERROR out of memory");
out_string(c, "SERVER_ERROR out of memory preparing response");
return;
}

Expand Down Expand Up @@ -2579,7 +2579,7 @@ static int try_read_network(conn *c) {
if (settings.verbose > 0)
fprintf(stderr, "Couldn't realloc input buffer\n");
c->rbytes = 0; /* ignore what we read */
out_string(c, "SERVER_ERROR out of memory");
out_string(c, "SERVER_ERROR out of memory reading request");
c->write_and_go = conn_closing;
return 1;
}
Expand Down
12 changes: 6 additions & 6 deletions memcached.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,8 @@ char *mt_item_stats_sizes(int *bytes);
void mt_item_unlink(item *it);
void mt_item_update(item *it);
void mt_run_deferred_deletes(void);
void *mt_slabs_alloc(size_t size);
void mt_slabs_free(void *ptr, size_t size);
void *mt_slabs_alloc(size_t size, unsigned int id);
void mt_slabs_free(void *ptr, size_t size, unsigned int id);
int mt_slabs_reassign(unsigned char srcid, unsigned char dstid);
char *mt_slabs_stats(int *buflen);
void mt_stats_lock(void);
Expand Down Expand Up @@ -392,8 +392,8 @@ int mt_store_item(item *item, int comm);
# define item_update(x) mt_item_update(x)
# define item_unlink(x) mt_item_unlink(x)
# define run_deferred_deletes() mt_run_deferred_deletes()
# define slabs_alloc(x) mt_slabs_alloc(x)
# define slabs_free(x,y) mt_slabs_free(x,y)
# define slabs_alloc(x,y) mt_slabs_alloc(x,y)
# define slabs_free(x,y,z) mt_slabs_free(x,y,z)
# define slabs_reassign(x,y) mt_slabs_reassign(x,y)
# define slabs_stats(x) mt_slabs_stats(x)
# define store_item(x,y) mt_store_item(x,y)
Expand Down Expand Up @@ -425,8 +425,8 @@ int mt_store_item(item *item, int comm);
# define item_unlink(x) do_item_unlink(x)
# define item_update(x) do_item_update(x)
# define run_deferred_deletes() do_run_deferred_deletes()
# define slabs_alloc(x) do_slabs_alloc(x)
# define slabs_free(x,y) do_slabs_free(x,y)
# define slabs_alloc(x,y) do_slabs_alloc(x,y)
# define slabs_free(x,y,z) do_slabs_free(x,y,z)
# define slabs_reassign(x,y) do_slabs_reassign(x,y)
# define slabs_stats(x) do_slabs_stats(x)
# define store_item(x,y) do_store_item(x,y)
Expand Down
2 changes: 1 addition & 1 deletion memcached.spec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Name: memcached
Version: 1.2.4
Version: 1.2.5
Release: 1%{?dist}
Summary: High Performance, Distributed Memory Object Cache

Expand Down
6 changes: 2 additions & 4 deletions slabs.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,9 @@ static int do_slabs_newslab(const unsigned int id) {
}

/*@null@*/
void *do_slabs_alloc(const size_t size) {
void *do_slabs_alloc(const size_t size, unsigned int id) {
slabclass_t *p;

unsigned int id = slabs_clsid(size);
if (id < POWER_SMALLEST || id > power_largest)
return NULL;

Expand Down Expand Up @@ -258,8 +257,7 @@ void *do_slabs_alloc(const size_t size) {
return NULL; /* shouldn't ever get here */
}

void do_slabs_free(void *ptr, const size_t size) {
unsigned char id = slabs_clsid(size);
void do_slabs_free(void *ptr, const size_t size, unsigned int id) {
slabclass_t *p;

assert(((item *)ptr)->slabs_clsid == 0);
Expand Down
4 changes: 2 additions & 2 deletions slabs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ void slabs_init(const size_t limit, const double factor, const bool prealloc);
unsigned int slabs_clsid(const size_t size);

/** Allocate object of given length. 0 on error */ /*@null@*/
void *do_slabs_alloc(const size_t size);
void *do_slabs_alloc(const size_t size, unsigned int id);

/** Free previously allocated object */
void do_slabs_free(void *ptr, size_t size);
void do_slabs_free(void *ptr, size_t size, unsigned int id);

/** Fill buffer with stats */ /*@null@*/
char* do_slabs_stats(int *buflen);
Expand Down
8 changes: 4 additions & 4 deletions thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,18 +571,18 @@ void mt_assoc_move_next_bucket() {

/******************************* SLAB ALLOCATOR ******************************/

void *mt_slabs_alloc(size_t size) {
void *mt_slabs_alloc(size_t size, unsigned int id) {
void *ret;

pthread_mutex_lock(&slabs_lock);
ret = do_slabs_alloc(size);
ret = do_slabs_alloc(size, id);
pthread_mutex_unlock(&slabs_lock);
return ret;
}

void mt_slabs_free(void *ptr, size_t size) {
void mt_slabs_free(void *ptr, size_t size, unsigned int id) {
pthread_mutex_lock(&slabs_lock);
do_slabs_free(ptr, size);
do_slabs_free(ptr, size, id);
pthread_mutex_unlock(&slabs_lock);
}

Expand Down

0 comments on commit 733db22

Please sign in to comment.