MINOR: quic: define sbuf pool

Define a new buffer pool reserved to allocate smaller memory area. For
the moment, its usage will be restricted to QUIC, as such it is declared
in quic_stream module.

Add a new config option "tune.bufsize.small" to specify the size of the
allocated objects. A special check ensures that it is not greater than
the default bufsize to avoid unexpected effects.
This commit is contained in:
Amaury Denoyelle 2024-08-13 09:34:28 +02:00
parent 1de5f718cf
commit d0d8e57d47
6 changed files with 69 additions and 0 deletions

View File

@ -1460,6 +1460,7 @@ The following keywords are supported in the "global" section :
- tune.buffers.limit - tune.buffers.limit
- tune.buffers.reserve - tune.buffers.reserve
- tune.bufsize - tune.bufsize
- tune.bufsize.small
- tune.comp.maxlevel - tune.comp.maxlevel
- tune.disable-fast-forward - tune.disable-fast-forward
- tune.disable-zero-copy-forwarding - tune.disable-zero-copy-forwarding
@ -3340,6 +3341,17 @@ tune.bufsize <number>
value set using this parameter will automatically be rounded up to the next 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. multiple of 8 on 32-bit machines and 16 on 64-bit machines.
tune.bufsize.small <number>
Sets the size in bytes for small buffers. The defaults value is 1024.
These buffers are designed to be used in some specific contexts where memory
consumption is restrained but it seems unnecessary to allocate a full buffer.
If however a small buffer is not sufficient, a reallocation is automatically
done to switch to a standard size buffer.
For the moment, it is used only by HTTP/3 protocol to emit the response
headers.
tune.comp.maxlevel <number> tune.comp.maxlevel <number>
Sets the maximum compression level. The compression level affects CPU Sets the maximum compression level. The compression level affects CPU
usage during compression. This value affects CPU usage during compression. usage during compression. This value affects CPU usage during compression.

View File

@ -71,6 +71,10 @@
#define BUFSIZE 16384 #define BUFSIZE 16384
#endif #endif
#ifndef BUFSIZE_SMALL
#define BUFSIZE_SMALL 1024
#endif
// number of per-thread emergency buffers for low-memory conditions // number of per-thread emergency buffers for low-memory conditions
#ifndef RESERVED_BUFS #ifndef RESERVED_BUFS
#define RESERVED_BUFS 4 #define RESERVED_BUFS 4

View File

@ -165,6 +165,7 @@ struct global {
int runqueue_depth;/* max number of tasks to run at once */ int runqueue_depth;/* max number of tasks to run at once */
int recv_enough; /* how many input bytes at once are "enough" */ int recv_enough; /* how many input bytes at once are "enough" */
int bufsize; /* buffer size in bytes, defaults to BUFSIZE */ int bufsize; /* buffer size in bytes, defaults to BUFSIZE */
int bufsize_small; /* small buffer size in bytes */
int maxrewrite; /* buffer max rewrite size in bytes, defaults to MAXREWRITE */ int maxrewrite; /* buffer max rewrite size in bytes, defaults to MAXREWRITE */
int reserved_bufs; /* how many buffers can only be allocated for response */ 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 */ int buf_limit; /* if not null, how many total buffers may only be allocated */

View File

@ -188,6 +188,34 @@ static int cfg_parse_tune_buffers_reserve(char **args, int section_type, struct
return 0; return 0;
} }
/* 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,
const char *file, int line, char **err)
{
int 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;
}
size = atol(args[1]);
if (size <= 0) {
memprintf(err, "'%s' expects a positive integer argument.\n", args[0]);
goto err;
}
global.tune.bufsize_small = size;
return 0;
err:
return -1;
}
/* allocate emergency buffers for the thread */ /* allocate emergency buffers for the thread */
static int alloc_emergency_buffers_per_thread(void) static int alloc_emergency_buffers_per_thread(void)
{ {
@ -227,6 +255,7 @@ static void free_emergency_buffers_per_thread(void)
static struct cfg_kw_list cfg_kws = {ILH, { static struct cfg_kw_list cfg_kws = {ILH, {
{ CFG_GLOBAL, "tune.buffers.limit", cfg_parse_tune_buffers_limit }, { CFG_GLOBAL, "tune.buffers.limit", cfg_parse_tune_buffers_limit },
{ CFG_GLOBAL, "tune.buffers.reserve", cfg_parse_tune_buffers_reserve }, { CFG_GLOBAL, "tune.buffers.reserve", cfg_parse_tune_buffers_reserve },
{ CFG_GLOBAL, "tune.bufsize.small", cfg_parse_tune_bufsize_small },
{ 0, NULL, NULL } { 0, NULL, NULL }
}}; }};

View File

@ -179,6 +179,7 @@ struct global global = {
.tune = { .tune = {
.options = GTUNE_LISTENER_MQ_OPT, .options = GTUNE_LISTENER_MQ_OPT,
.bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)), .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
.bufsize_small = BUFSIZE_SMALL,
.maxrewrite = MAXREWRITE, .maxrewrite = MAXREWRITE,
.reserved_bufs = RESERVED_BUFS, .reserved_bufs = RESERVED_BUFS,
.pattern_cache = DEFAULT_PAT_LRU_SIZE, .pattern_cache = DEFAULT_PAT_LRU_SIZE,

View File

@ -5,6 +5,7 @@
#include <haproxy/api.h> #include <haproxy/api.h>
#include <haproxy/buf.h> #include <haproxy/buf.h>
#include <haproxy/dynbuf.h> #include <haproxy/dynbuf.h>
#include <haproxy/errors.h>
#include <haproxy/list.h> #include <haproxy/list.h>
#include <haproxy/mux_quic.h> #include <haproxy/mux_quic.h>
#include <haproxy/pool.h> #include <haproxy/pool.h>
@ -16,6 +17,7 @@ DECLARE_STATIC_POOL(pool_head_quic_stream_desc, "qc_stream_desc",
DECLARE_STATIC_POOL(pool_head_quic_stream_buf, "qc_stream_buf", DECLARE_STATIC_POOL(pool_head_quic_stream_buf, "qc_stream_buf",
sizeof(struct qc_stream_buf)); sizeof(struct qc_stream_buf));
static struct pool_head *pool_head_sbuf;
/* Returns true if nothing to ack yet for stream <s> including FIN bit. */ /* Returns true if nothing to ack yet for stream <s> including FIN bit. */
static inline int qc_stream_desc_done(const struct qc_stream_desc *s) static inline int qc_stream_desc_done(const struct qc_stream_desc *s)
@ -300,3 +302,23 @@ void qc_stream_buf_release(struct qc_stream_desc *stream)
stream->buf = NULL; stream->buf = NULL;
stream->buf_offset = 0; stream->buf_offset = 0;
} }
static int create_sbuf_pool(void)
{
if (global.tune.bufsize_small > global.tune.bufsize) {
ha_warning("invalid small buffer size %d bytes which is greater to default bufsize %d bytes.\n",
global.tune.bufsize_small, global.tune.bufsize);
return ERR_FATAL|ERR_ABORT;
}
pool_head_sbuf = create_pool("sbuf", global.tune.bufsize_small,
MEM_F_SHARED|MEM_F_EXACT);
if (!pool_head_sbuf) {
ha_warning("error on small buffer pool allocation.\n");
return ERR_FATAL|ERR_ABORT;
}
return ERR_NONE;
}
REGISTER_POST_CHECK(create_sbuf_pool);