Skip to content

Commit

Permalink
Try to recycle allocated memory from expired items before allocating …
Browse files Browse the repository at this point in the history
  • Loading branch information
Trond Norbye authored and dustin committed Mar 17, 2009
1 parent 4f5e185 commit d3807d0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 5 deletions.
34 changes: 29 additions & 5 deletions items.c
Expand Up @@ -85,7 +85,7 @@ static size_t item_make_header(const uint8_t nkey, const int flags, const int nb
/*@null@*/
item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_time_t exptime, const int nbytes) {
uint8_t nsuffix;
item *it;
item *it = NULL;
char suffix[40];
size_t ntotal = item_make_header(nkey + 1, flags, nbytes, suffix, &nsuffix);
if (settings.use_cas) {
Expand All @@ -96,10 +96,34 @@ 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, id);
if (it == 0) {
int tries = 50;
item *search;
/* do a quick check if we have any expired items in the tail.. */
int tries = 50;
item *search;

for (search = tails[id];
tries > 0 && search != NULL;
tries--, search=search->prev) {
if (search->refcount == 0 &&
(search->exptime != 0 && search->exptime < current_time)) {
it = search;
/* I don't want to actually free the object, just steal
* the item to avoid to grab the slab mutex twice ;-)
*/
it->refcount = 1;
do_item_unlink(it);
/* Initialize the item block: */
it->slabs_clsid = 0;
it->refcount = 0;
break;
}
}

if (it == NULL && (it = slabs_alloc(ntotal, id)) == NULL) {
/*
** Could not find an expired item at the tail, and memory allocation
** failed. Try to evict some items!
*/
tries = 50;

/* If requested to not push old items out of cache when memory runs out,
* we're out of luck at this point...
Expand Down
34 changes: 34 additions & 0 deletions t/issue_14.t
@@ -0,0 +1,34 @@
#!/usr/bin/perl

use strict;
use Test::More tests => 21;
use FindBin qw($Bin);
use lib "$Bin/lib";
use MemcachedTest;

my $server = new_memcached();
my $sock = $server->sock;
my $value = "B"x66560;
my $key = 0;

for ($key = 0; $key < 10; $key++) {
print $sock "set key$key 0 2 66560\r\n$value\r\n";
is (scalar <$sock>, "STORED\r\n", "stored key$key");
}

#print $sock "stats slabs"
my $first_stats = mem_stats($sock, "slabs");
my $first_malloc = $first_stats->{total_malloced};

sleep(4);

for ($key = 10; $key < 20; $key++) {
print $sock "set key$key 0 2 66560\r\n$value\r\n";
is (scalar <$sock>, "STORED\r\n", "stored key$key");
}

my $second_stats = mem_stats($sock, "slabs");
my $second_malloc = $second_stats->{total_malloced};


is ($second_malloc, $first_malloc, "Memory grows..")

0 comments on commit d3807d0

Please sign in to comment.