mirror of
https://github.com/haproxy/haproxy.git
synced 2026-02-18 18:19:39 -05:00
MEDIUM: dynbuf: Add a pool for large buffers with a configurable size
Add the support for large bufers. A dedicated memory pool is added. The size of these buffers must be explicitly configured by setting "tune.bufsize.large" directive. If it is not set, the pool is not created. In addition, if the size for large buffers is the same than for regular buffer, the feature is automatically disable. For now, large buffers remain unused.
This commit is contained in:
parent
ee309bafcf
commit
d89ec33a34
7 changed files with 72 additions and 1 deletions
|
|
@ -1869,6 +1869,7 @@ The following keywords are supported in the "global" section :
|
|||
- tune.buffers.limit
|
||||
- tune.buffers.reserve
|
||||
- tune.bufsize
|
||||
- tune.bufsize.large
|
||||
- tune.bufsize.small
|
||||
- tune.comp.maxlevel
|
||||
- tune.defaults.purge
|
||||
|
|
@ -4118,6 +4119,14 @@ tune.bufsize <size>
|
|||
value set using this parameter will automatically be rounded up to the next
|
||||
multiple of 8 on 32-bit machines and 16 on 64-bit machines.
|
||||
|
||||
tune.bufsize.large <size>
|
||||
Sets the size in butes for large buffers. By defaults, support for large
|
||||
buffers is not enabled, it must explicitly be enable by setting this value.
|
||||
|
||||
These buffers are designed to be used in some specific contexts where more
|
||||
data must be bufferized without changing the size of regular buffers. The
|
||||
large buffers are not implicitly used.
|
||||
|
||||
tune.bufsize.small <size>
|
||||
Sets the size in bytes for small buffers. The defaults value is 1024.
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include <haproxy/pool.h>
|
||||
|
||||
extern struct pool_head *pool_head_buffer;
|
||||
extern struct pool_head *pool_head_large_buffer;
|
||||
|
||||
int init_buffer(void);
|
||||
void buffer_dump(FILE *o, struct buffer *b, int from, int to);
|
||||
|
|
@ -136,13 +137,18 @@ static inline char *__b_get_emergency_buf(void)
|
|||
#define __b_free(_buf) \
|
||||
do { \
|
||||
char *area = (_buf)->area; \
|
||||
size_t sz = (_buf)->size; \
|
||||
\
|
||||
/* let's first clear the area to save an occasional "show sess all" \
|
||||
* glancing over our shoulder from getting a dangling pointer. \
|
||||
*/ \
|
||||
*(_buf) = BUF_NULL; \
|
||||
__ha_barrier_store(); \
|
||||
if (th_ctx->emergency_bufs_left < global.tune.reserved_bufs) \
|
||||
/* if enabled, large buffers are always strictly greater \
|
||||
* than the default buffers */ \
|
||||
if (unlikely(pool_head_large_buffer && sz == pool_head_large_buffer->size)) \
|
||||
pool_free(pool_head_large_buffer, area); \
|
||||
else if (th_ctx->emergency_bufs_left < global.tune.reserved_bufs) \
|
||||
th_ctx->emergency_bufs[th_ctx->emergency_bufs_left++] = area; \
|
||||
else \
|
||||
pool_free(pool_head_buffer, area); \
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ struct global {
|
|||
uint recv_enough; /* how many input bytes at once are "enough" */
|
||||
uint bufsize; /* buffer size in bytes, defaults to BUFSIZE */
|
||||
uint bufsize_small;/* small buffer size in bytes */
|
||||
uint bufsize_large;/* large buffer size in bytes */
|
||||
int maxrewrite; /* buffer max rewrite size in bytes, defaults to MAXREWRITE */
|
||||
int reserved_bufs; /* how many buffers can only be allocated for response */
|
||||
int buf_limit; /* if not null, how many total buffers may only be allocated */
|
||||
|
|
|
|||
|
|
@ -2311,6 +2311,17 @@ int check_config_validity()
|
|||
global.nbthread = global.thread_limit;
|
||||
}
|
||||
|
||||
if (global.tune.bufsize_large > 0) {
|
||||
if (global.tune.bufsize_large == global.tune.bufsize)
|
||||
global.tune.bufsize_large = 0;
|
||||
else if (global.tune.bufsize_large < global.tune.bufsize) {
|
||||
ha_warning("tune.bufsize.large (%u) is lower than tune.bufsize (%u). large buffers support is disabled. "
|
||||
"Please fix either value to remove this warning.\n",
|
||||
global.tune.bufsize_large, global.tune.bufsize);
|
||||
global.tune.bufsize_large = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* in the worst case these were supposed to be set in thread_detect_count() */
|
||||
BUG_ON(!global.nbthread);
|
||||
BUG_ON(!global.nbtgroups);
|
||||
|
|
|
|||
42
src/dynbuf.c
42
src/dynbuf.c
|
|
@ -23,6 +23,7 @@
|
|||
#include <haproxy/tools.h>
|
||||
|
||||
struct pool_head *pool_head_buffer __read_mostly;
|
||||
struct pool_head *pool_head_large_buffer __read_mostly = NULL;
|
||||
|
||||
/* perform minimal initializations, report 0 in case of error, 1 if OK. */
|
||||
int init_buffer()
|
||||
|
|
@ -36,6 +37,12 @@ int init_buffer()
|
|||
if (!pool_head_buffer)
|
||||
return 0;
|
||||
|
||||
if (global.tune.bufsize_large) {
|
||||
pool_head_large_buffer = create_aligned_pool("large_buffer", global.tune.bufsize_large, 64, MEM_F_SHARED|MEM_F_EXACT);
|
||||
if (!pool_head_large_buffer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* make sure any change to the queues assignment isn't overlooked */
|
||||
BUG_ON(DB_PERMANENT - DB_UNLIKELY - 1 != DYNBUF_NBQ);
|
||||
BUG_ON(DB_MUX_RX_Q < DB_SE_RX_Q || DB_MUX_RX_Q >= DYNBUF_NBQ);
|
||||
|
|
@ -188,6 +195,40 @@ static int cfg_parse_tune_buffers_reserve(char **args, int section_type, struct
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* config parse for global "tune.bufsize.large" */
|
||||
static int cfg_parse_tune_bufsize_large(char **args, int section_type,
|
||||
struct proxy *curpx, const struct proxy *defpx,
|
||||
const char *file, int line, char **err)
|
||||
{
|
||||
const char *res;
|
||||
uint size;
|
||||
|
||||
if (too_many_args(1, args, err, NULL))
|
||||
goto err;
|
||||
|
||||
if (*(args[1]) == 0) {
|
||||
memprintf(err, "'%s' expects an integer argument.\n", args[0]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
res = parse_size_err(args[1], &size);
|
||||
if (res != NULL) {
|
||||
memprintf(err, "unexpected '%s' after size passed to '%s'", res, args[0]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (size <= 0) {
|
||||
memprintf(err, "'%s' expects a positive integer argument.\n", args[0]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
global.tune.bufsize_large = size;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* config parse for global "tune.bufsize.small" */
|
||||
static int cfg_parse_tune_bufsize_small(char **args, int section_type,
|
||||
struct proxy *curpx, const struct proxy *defpx,
|
||||
|
|
@ -261,6 +302,7 @@ static void free_emergency_buffers_per_thread(void)
|
|||
static struct cfg_kw_list cfg_kws = {ILH, {
|
||||
{ CFG_GLOBAL, "tune.buffers.limit", cfg_parse_tune_buffers_limit },
|
||||
{ CFG_GLOBAL, "tune.buffers.reserve", cfg_parse_tune_buffers_reserve },
|
||||
{ CFG_GLOBAL, "tune.bufsize.large", cfg_parse_tune_bufsize_large },
|
||||
{ CFG_GLOBAL, "tune.bufsize.small", cfg_parse_tune_bufsize_small },
|
||||
{ 0, NULL, NULL }
|
||||
}};
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ struct global global = {
|
|||
.options = GTUNE_LISTENER_MQ_OPT,
|
||||
.bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
|
||||
.bufsize_small = BUFSIZE_SMALL,
|
||||
.bufsize_large = 0,
|
||||
.maxrewrite = MAXREWRITE,
|
||||
.reserved_bufs = RESERVED_BUFS,
|
||||
.pattern_cache = DEFAULT_PAT_LRU_SIZE,
|
||||
|
|
|
|||
|
|
@ -764,6 +764,7 @@ void stream_free(struct stream *s)
|
|||
/* We may want to free the maximum amount of pools if the proxy is stopping */
|
||||
if (fe && unlikely(fe->flags & (PR_FL_DISABLED|PR_FL_STOPPED))) {
|
||||
pool_flush(pool_head_buffer);
|
||||
pool_flush(pool_head_large_buffer);
|
||||
pool_flush(pool_head_http_txn);
|
||||
pool_flush(pool_head_requri);
|
||||
pool_flush(pool_head_capture);
|
||||
|
|
|
|||
Loading…
Reference in a new issue