[MEDIUM] enhance behaviour of mempools v2

- keep the number of users of each pool
- call the garbage collector on out of memory conditions
- sort the pools by size for faster creation
- force the alignment size to 16 bytes instead of 4*sizeof(void *)
This commit is contained in:
Willy Tarreau 2007-05-14 00:16:13 +02:00
parent 1d4154a7c0
commit 7dcd46d471
2 changed files with 32 additions and 14 deletions

View File

@ -125,7 +125,8 @@ struct pool_head {
unsigned int minavail; /* how many chunks are expected to be used */ unsigned int minavail; /* how many chunks are expected to be used */
unsigned int size; /* chunk size */ unsigned int size; /* chunk size */
unsigned int flags; /* MEM_F_* */ unsigned int flags; /* MEM_F_* */
char name[9]; /* name of the pool */ unsigned int users; /* number of pools sharing this zone */
char name[12]; /* name of the pool */
}; };

View File

@ -26,6 +26,8 @@ static struct list pools = LIST_HEAD_INIT(pools);
struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags) struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
{ {
struct pool_head *pool; struct pool_head *pool;
struct pool_head *entry;
struct list *start;
unsigned int align; unsigned int align;
/* We need to store at least a (void *) in the chunks. Since we know /* We need to store at least a (void *) in the chunks. Since we know
@ -34,20 +36,29 @@ struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
* ease merging of entries. Note that the rounding is a power of two. * ease merging of entries. Note that the rounding is a power of two.
*/ */
align = 4 * sizeof(void *); align = 16;
size = (size + align - 1) & -align; size = (size + align - 1) & -align;
start = &pools;
pool = NULL; pool = NULL;
if (flags & MEM_F_SHARED) {
struct pool_head *entry; list_for_each_entry(entry, &pools, list) {
list_for_each_entry(entry, &pools, list) { if (entry->size == size) {
if (!(entry->flags & MEM_F_SHARED)) /* either we can share this place and we take it, or
continue; * we look for a sharable one or for the next position
if (entry->size == size) { * before which we will insert a new one.
*/
if (flags & entry->flags & MEM_F_SHARED) {
/* we can share this one */
pool = entry; pool = entry;
break; break;
} }
} }
else if (entry->size > size) {
/* insert before this one */
start = &entry->list;
break;
}
} }
if (!pool) { if (!pool) {
@ -58,13 +69,15 @@ struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
strlcpy2(pool->name, name, sizeof(pool->name)); strlcpy2(pool->name, name, sizeof(pool->name));
pool->size = size; pool->size = size;
pool->flags = flags; pool->flags = flags;
LIST_ADDQ(&pools, &pool->list); LIST_ADDQ(start, &pool->list);
} }
pool->users++;
return pool; return pool;
} }
/* Allocate a new entry for pool <pool>, and return it for immediate use. /* Allocate a new entry for pool <pool>, and return it for immediate use.
* NULL is returned if no memory is available for a new creation. * NULL is returned if no memory is available for a new creation. A call
* to the garbage collector is performed before returning NULL.
*/ */
void *pool_refill_alloc(struct pool_head *pool) void *pool_refill_alloc(struct pool_head *pool)
{ {
@ -73,8 +86,12 @@ void *pool_refill_alloc(struct pool_head *pool)
if (pool->limit && (pool->allocated >= pool->limit)) if (pool->limit && (pool->allocated >= pool->limit))
return NULL; return NULL;
ret = MALLOC(pool->size); ret = MALLOC(pool->size);
if (!ret) if (!ret) {
return NULL; pool_gc2();
ret = MALLOC(pool->size);
if (!ret)
return NULL;
}
pool->allocated++; pool->allocated++;
pool->used++; pool->used++;
return ret; return ret;
@ -142,10 +159,10 @@ void dump_pools(void)
allocated = used = nbpools = 0; allocated = used = nbpools = 0;
qfprintf(stderr, "Dumping pools usage.\n"); qfprintf(stderr, "Dumping pools usage.\n");
list_for_each_entry(entry, &pools, list) { list_for_each_entry(entry, &pools, list) {
qfprintf(stderr, " - Pool %s (%d bytes) : %d allocated (%lu bytes), %d used%s\n", qfprintf(stderr, " - Pool %s (%d bytes) : %d allocated (%lu bytes), %d used, %d users%s\n",
entry->name, entry->size, entry->allocated, entry->name, entry->size, entry->allocated,
entry->size * entry->allocated, entry->used, entry->size * entry->allocated, entry->used,
(entry->flags & MEM_F_SHARED) ? " [SHARED]" : ""); entry->users, (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
allocated += entry->allocated * entry->size; allocated += entry->allocated * entry->size;
used += entry->used * entry->size; used += entry->used * entry->size;