]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] enhance behaviour of mempools v2
authorWilly Tarreau <w@1wt.eu>
Sun, 13 May 2007 22:16:13 +0000 (00:16 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 13 May 2007 22:16:13 +0000 (00:16 +0200)
- 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 *)

include/common/memory.h
src/memory.c

index 45ac7f962a81ad04c8b9681ea47de37f5f6da843..66f789e25a1dda1bfd09656d77f85f721ee4a431 100644 (file)
@@ -125,7 +125,8 @@ struct pool_head {
        unsigned int minavail;  /* how many chunks are expected to be used */
        unsigned int size;      /* chunk size */
        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 */
 };
 
 
index dd542252bbbae3a25f62a9665e0b944b3e783c93..589d1d2706471068bab7f85a486fca9baef7bd3f 100644 (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 *pool;
+       struct pool_head *entry;
+       struct list *start;
        unsigned int align;
 
        /* 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.
         */
 
-       align = 4 * sizeof(void *);
+       align = 16;
        size  = (size + align - 1) & -align;
 
+       start = &pools;
        pool = NULL;
-       if (flags & MEM_F_SHARED) {
-               struct pool_head *entry;
-               list_for_each_entry(entry, &pools, list) {
-                       if (!(entry->flags & MEM_F_SHARED))
-                               continue;
-                       if (entry->size == size) {
+
+       list_for_each_entry(entry, &pools, list) {
+               if (entry->size == size) {
+                       /* either we can share this place and we take it, or
+                        * we look for a sharable one or for the next position
+                        * before which we will insert a new one.
+                        */
+                       if (flags & entry->flags & MEM_F_SHARED) {
+                               /* we can share this one */
                                pool = entry;
                                break;
                        }
                }
+               else if (entry->size > size) {
+                       /* insert before this one */
+                       start = &entry->list;
+                       break;
+               }
        }
 
        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));
                pool->size = size;
                pool->flags = flags;
-               LIST_ADDQ(&pools, &pool->list);
+               LIST_ADDQ(start, &pool->list);
        }
+       pool->users++;
        return pool;
 }
 
 /* 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)
 {
@@ -73,8 +86,12 @@ void *pool_refill_alloc(struct pool_head *pool)
        if (pool->limit && (pool->allocated >= pool->limit))
                return NULL;
        ret = MALLOC(pool->size);
-       if (!ret)
-               return NULL;
+       if (!ret) {
+               pool_gc2();
+               ret = MALLOC(pool->size);
+               if (!ret)
+                       return NULL;
+       }
        pool->allocated++;
        pool->used++;
        return ret;
@@ -142,10 +159,10 @@ void dump_pools(void)
        allocated = used = nbpools = 0;
        qfprintf(stderr, "Dumping pools usage.\n");
        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->size * entry->allocated, entry->used,
-                        (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
+                        entry->users, (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
 
                allocated += entry->allocated * entry->size;
                used += entry->used * entry->size;