]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] implement memory pools version 2
authorWilly Tarreau <w@1wt.eu>
Sun, 13 May 2007 16:26:08 +0000 (18:26 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 13 May 2007 16:26:08 +0000 (18:26 +0200)
The new pools know about their size and usage. Malloc is not used
anymore, instead a dedicated function to refill the entries is used.

Makefile
Makefile.bsd
Makefile.osx
include/common/config.h
include/common/memory.h
src/memory.c [new file with mode: 0644]

index c7017e5eafa008224f0b232f3cafc9ce5902439b..122f1c6fa8f4b909b0b7452d64ba66ca4318e0f1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -217,7 +217,7 @@ OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
        src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
        src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
        src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
-       src/session.o src/hdr_idx.o src/ev_select.o src/acl.o
+       src/session.o src/hdr_idx.o src/ev_select.o src/acl.o src/memory.o
 
 haproxy: $(OBJS) $(OPT_OBJS)
        $(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
index 76fe256bcdd7d840f324a6a76032c21a9592a7cf..945b08e24cda941e58d1a82d179c8698b55a1e8e 100644 (file)
@@ -88,7 +88,7 @@ OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
        src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
        src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
        src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o \
-       src/ev_kqueue.o src/acl.o
+       src/ev_kqueue.o src/acl.o src/memory.o
 
 all: haproxy
 
index 15db775cd8790bedb049cf02b0304e652cf54bfe..0618e68c9c299aec7a7d91972bd7c7ce949d63e5 100644 (file)
@@ -87,7 +87,8 @@ OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \
        src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
        src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \
        src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
-       src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o src/acl.o
+       src/session.o src/hdr_idx.o src/ev_select.o src/ev_poll.o src/acl.o \
+       src/memory.o
 
 all: haproxy
 
index e8d8ad26bff67f10198a48b6d16a250c745add1f..85deeaed5f97efd5e9a0226433a5a0627b690e28 100644 (file)
@@ -2,7 +2,7 @@
   include/common/config.h
   This files contains most of the user-configurable settings.
 
-  Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+  Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
 #  define CONFIG_HAP_MEM_OPTIM
 #endif /* CONFIG_HAP_NO_MEM_OPTIM */
 
+/* CONFIG_HAP_MALLOC / CONFIG_HAP_CALLOC / CONFIG_HAP_FREE
+ * This macro allows to replace the malloc function with another one.
+ */
+#ifdef CONFIG_HAP_MALLOC
+#define MALLOC CONFIG_HAP_MALLOC
+#else
+#define MALLOC malloc
+#endif
+
+#ifdef CONFIG_HAP_CALLOC
+#define CALLOC CONFIG_HAP_CALLOC
+#else
+#define CALLOC calloc
+#endif
+
+#ifdef CONFIG_HAP_FREE
+#define FREE   CONFIG_HAP_FREE
+#else
+#define FREE   free
+#endif
+
 
 /* CONFIG_HAP_INLINE_FD_SET
  * This makes use of inline FD_* macros instead of calling equivalent
index 820c1d98e18bbb66f2889771e53e7ccb5af7c16f..77346b706ef9d5f05774cf6f6ef6e2d6de325053 100644 (file)
@@ -2,7 +2,7 @@
   include/common/memory.h
   Memory management definitions..
 
-  Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+  Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 
 #include <common/config.h>
+#include <common/mini-clist.h>
 
 #define sizeof_requri   REQURI_LEN
 #define sizeof_capture  CAPTURE_LEN
@@ -112,6 +113,73 @@ static inline void pool_destroy(void **pool)
        }
 }
 
+
+/******* pools version 2 ********/
+
+#define MEM_F_SHARED   0x1
+
+struct pool_head {
+       void **free_list;
+       struct list list;       /* list of all known pools */
+       unsigned int used;      /* how many chunks are currently in use */
+       unsigned int allocated; /* how many chunks have been allocated */
+       unsigned int limit;     /* hard limit on the number of chunks */
+       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 */
+};
+
+
+/* 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.
+ */
+void *refill_pool_alloc(struct pool_head *pool);
+
+/* Try to find an existing shared pool with the same characteristics and
+ * returns it, otherwise creates this one. NULL is returned if no memory
+ * is available for a new creation.
+ */
+struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags);
+
+/* Dump statistics on pools usage.
+ */
+void dump_pools(void);
+
+/*
+ * Returns a pointer to type <type> taken from the
+ * pool <pool_type> or dynamically allocated. In the
+ * first case, <pool_type> is updated to point to the
+ * next element in the list.
+ */
+#define pool_alloc2(pool)                                       \
+({                                                              \
+        void *__p;                                              \
+        if ((__p = pool.free_list) == NULL)                     \
+                __p = pool_refill_alloc(&pool);                 \
+        else {                                                  \
+                pool.free_list = *(void **)pool.free_list;      \
+                pool.used++;                                    \
+        }                                                       \
+        __p;                                                    \
+})
+
+/*
+ * Puts a memory area back to the corresponding pool.
+ * Items are chained directly through a pointer that
+ * is written in the beginning of the memory area, so
+ * there's no need for any carrier cell. This implies
+ * that each memory area is at least as big as one
+ * pointer.
+ */
+#define pool_free2(pool, ptr)                           \
+({                                                      \
+        *(void **)ptr = (void *)pool.free_list;         \
+        pool.free_list = (void *)ptr;                   \
+        pool.used--;                                    \
+})
+
+
 #endif /* _COMMON_MEMORY_H */
 
 /*
diff --git a/src/memory.c b/src/memory.c
new file mode 100644 (file)
index 0000000..5dbbdd9
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Memory management functions.
+ *
+ * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <common/config.h>
+#include <common/memory.h>
+#include <common/mini-clist.h>
+#include <common/standard.h>
+
+#include <proto/log.h>
+
+static struct list pools = LIST_HEAD_INIT(pools);
+
+/* Try to find an existing shared pool with the same characteristics and
+ * returns it, otherwise creates this one. NULL is returned if no memory
+ * is available for a new creation.
+ */
+struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
+{
+       struct pool_head *pool;
+       unsigned int align;
+
+       /* We need to store at least a (void *) in the chunks. Since we know
+        * that the malloc() function will never return such a small size,
+        * let's round the size up to something slightly bigger, in order to
+        * ease merging of entries. Note that the rounding is a power of two.
+        */
+
+       align = 4 * sizeof(void *);
+       size  = (size + align - 1) & -align;
+
+       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) {
+                               pool = entry;
+                               break;
+                       }
+               }
+       }
+
+       if (!pool) {
+               pool = CALLOC(1, sizeof(*pool));
+               if (!pool)
+                       return NULL;
+               if (name)
+                       strlcpy2(pool->name, name, sizeof(pool->name));
+               pool->size = size;
+               pool->flags = flags;
+               LIST_ADDQ(&pools, &pool->list);
+       }
+       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.
+ */
+void *refill_pool_alloc(struct pool_head *pool)
+{
+       void *ret;
+
+       if (pool->limit && (pool->allocated >= pool->limit))
+               return NULL;
+       ret = MALLOC(pool->size);
+       if (!ret)
+               return NULL;
+       pool->allocated++;
+       pool->used++;
+       return ret;
+}
+
+/* Dump statistics on pools usage.
+ */
+void dump_pools(void)
+{
+       struct pool_head *entry;
+       unsigned long allocated, used;
+       int nbpools;
+
+       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, %d used%s\n",
+                        entry->name, entry->size, entry->allocated, entry->used,
+                        (entry->flags & MEM_F_SHARED) ? " (SHARED)" : "");
+
+               allocated += entry->allocated * entry->size;
+               used += entry->used * entry->size;
+               nbpools++;
+       }
+       qfprintf(stderr, "Total: %d pools, %lu allocated, %lu used.\n",
+                nbpools, allocated, used);
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */