[MEDIUM] implement memory pools version 2
The new pools know about their size and usage. Malloc is not used anymore, instead a dedicated function to refill the entries is used.
This commit is contained in:
parent
aff694f3b6
commit
50e608d721
2
Makefile
2
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/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/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/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)
|
haproxy: $(OBJS) $(OPT_OBJS)
|
||||||
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
|
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
|
@ -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/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/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/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
|
all: haproxy
|
||||||
|
|
||||||
|
|
|
@ -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/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/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/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
|
all: haproxy
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
include/common/config.h
|
include/common/config.h
|
||||||
This files contains most of the user-configurable settings.
|
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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -39,6 +39,27 @@
|
||||||
# define CONFIG_HAP_MEM_OPTIM
|
# define CONFIG_HAP_MEM_OPTIM
|
||||||
#endif /* CONFIG_HAP_NO_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
|
/* CONFIG_HAP_INLINE_FD_SET
|
||||||
* This makes use of inline FD_* macros instead of calling equivalent
|
* This makes use of inline FD_* macros instead of calling equivalent
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
include/common/memory.h
|
include/common/memory.h
|
||||||
Memory management definitions..
|
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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <common/config.h>
|
#include <common/config.h>
|
||||||
|
#include <common/mini-clist.h>
|
||||||
|
|
||||||
#define sizeof_requri REQURI_LEN
|
#define sizeof_requri REQURI_LEN
|
||||||
#define sizeof_capture CAPTURE_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 */
|
#endif /* _COMMON_MEMORY_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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:
|
||||||
|
*/
|
Loading…
Reference in New Issue