From 0262241e265fc615047e9156c65f805814357280 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 8 Dec 2014 16:35:23 +0100 Subject: [PATCH] MINOR: memory: cut pool allocator in 3 layers pool_alloc2() used to pick the entry from the pool, fall back to pool_refill_alloc(), and to perform the poisonning itself, which pool_refill_alloc() was also doing. While this led to optimal code size, it imposes memory poisonning on the buffers as well, which is extremely slow on large buffers. This patch cuts the allocator in 3 layers : - a layer to pick the first entry from the pool without falling back to pool_refill_alloc() : pool_get_first() - a layer to allocate a dirty area by falling back to pool_refill_alloc() but never performing the poisonning : pool_alloc_dirty() - pool_alloc2() which calls the latter and optionally poisons the area No functional changes were made. --- include/common/memory.h | 51 ++++++++++++++++++++++++++++++----------- src/memory.c | 2 -- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/include/common/memory.h b/include/common/memory.h index 330d7ff51a..3a0eaf6955 100644 --- a/include/common/memory.h +++ b/include/common/memory.h @@ -95,24 +95,49 @@ void pool_gc2(); void *pool_destroy2(struct pool_head *pool); /* - * Returns a pointer to type taken from the - * pool or dynamically allocated. In the - * first case, is updated to point to the - * next element in the list. + * Returns a pointer to type taken from the pool if + * available, otherwise returns NULL. No malloc() is attempted, and poisonning + * is never performed. The purpose is to get the fastest possible allocation. + */ +static inline void *pool_get_first(struct pool_head *pool) +{ + void *p; + + if ((p = pool->free_list) != NULL) { + pool->free_list = *(void **)pool->free_list; + pool->used++; + } + return p; +} + +/* + * Returns a pointer to type taken from the pool or + * dynamically allocated. In the first case, is updated to point to + * the next element in the list. No memory poisonning is ever performed on the + * returned area. + */ +static inline void *pool_alloc_dirty(struct pool_head *pool) +{ + void *p; + + if ((p = pool_get_first(pool)) == NULL) + p = pool_refill_alloc(pool); + + return p; +} + +/* + * Returns a pointer to type taken from the pool or + * dynamically allocated. In the first case, is updated to point to + * the next element in the list. Memory poisonning is performed if enabled. */ static inline void *pool_alloc2(struct pool_head *pool) { void *p; - if ((p = pool->free_list) == NULL) { - p = pool_refill_alloc(pool); - } - else { - pool->free_list = *(void **)pool->free_list; - pool->used++; - if (unlikely(mem_poison_byte)) - memset(p, mem_poison_byte, pool->size); - } + p = pool_alloc_dirty(pool); + if (p && mem_poison_byte) + memset(p, mem_poison_byte, pool->size); return p; } diff --git a/src/memory.c b/src/memory.c index fcd7679314..3fbc520594 100644 --- a/src/memory.c +++ b/src/memory.c @@ -96,8 +96,6 @@ void *pool_refill_alloc(struct pool_head *pool) if (!ret) return NULL; } - if (mem_poison_byte) - memset(ret, mem_poison_byte, pool->size); pool->allocated++; pool->used++; return ret;