]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: proxy: Add use-small-buffers option to set where to use small buffers
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 19 Mar 2026 13:19:37 +0000 (14:19 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 23 Mar 2026 13:02:43 +0000 (14:02 +0100)
Thanks to previous commits, it is possible to use small buffers at different
places: to store the request when a connection is queued or when L7 retries
are enabled, or for health-checks requests. However, there was no
configuration parameter to fine tune small buffer use.

It is now possible, thanks to the proxy option "use-small-buffers".
Documentation was updated accordingly.

doc/configuration.txt
include/haproxy/proxy-t.h
src/cfgparse-listen.c
src/check.c
src/stconn.c
src/stream.c

index 968c031dc305cedda0d3e13195c8dff34adbddad..a5195a1d70ff91fad73e65880657e621c3c61318 100644 (file)
@@ -4165,8 +4165,11 @@ tune.bufsize.small <size>
   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.
+  For the moment, it is automatically used only by HTTP/3 protocol to emit the
+  response headers. Otherwise, small buffers support can be enabled for
+  specific proxies via the "use-small-buffers" option.
+
+  See also: option use-small-buffers
 
 tune.comp.maxlevel <number>
   Sets the maximum compression level. The compression level affects CPU
@@ -6066,6 +6069,7 @@ option tcp-smart-connect             (*)  X          -         X         X
 option tcpka                              X          X         X         X
 option tcplog                             X          X         X         -
 option transparent      (deprecated) (*)  X          -         X         X
+option use-small-buffers             (*)  X          -         X         X
 persist rdp-cookie                        X          -         X         X
 quic-initial                              X (!)      X         X         -
 rate-limit sessions                       X          X         X         -
@@ -11905,6 +11909,36 @@ no option transparent     (deprecated)
             "transparent" option of the "bind" keyword.
 
 
+option use-small-buffers [ queue | l7-retries | check ]*
+
+  Enable support for small buffers for the given categories.
+
+  May be used in the following contexts: tcp, http
+
+  May be used in sections :   defaults | frontend | listen | backend
+                                 yes   |    no    |   yes  |   yes
+
+  This option can be used to enable the small buffers support at diffent places
+  to save memory. By default, with no parameter, small buffers are used as far
+  as possible at all possible places. Otherwise, it is possible to limit it to
+  following the places:
+
+   - queue:      When set, small buffers will be used to store the requests, if
+                 small enough, when the connection is queued.
+   - l7-retries: When set, small buffers will be used to save the requests
+                 when L7 retries are enabled.
+   - check:      When set, small buffers will be used for the health-checks
+                 requests.
+
+  When enabled, small buffers are used, but only if it is possible. Otherwise,
+  when data are too large, a regular buffer is automtically used. The size of
+  small buffers is configurable via the "tune.bufsize.small" global setting.
+
+  If this option has been enabled in a "defaults" section, it can be disabled
+  in a specific instance by prepending the "no" keyword before it.
+
+  See also: tune.bufsize.small
+
 persist rdp-cookie
 persist rdp-cookie(<name>)
   Enable RDP cookie-based persistence
index fbd9e3ca3cae76abc896917d7e55f2079e48eb92..07ef037daf60fc1bdeb9681f9305b7c8fd56365f 100644 (file)
@@ -162,7 +162,11 @@ enum PR_SRV_STATE_FILE {
 #define PR_O2_EXT_CHK    0x04000000    /* use external command for server health */
 #define PR_O2_CHK_ANY    0x06000000    /* Mask to cover any check */
 
-/* unused : 0x08000000 ... 0x80000000 */
+#define PR_O2_USE_SBUF_QUEUE    0x08000000 /* use small buffer for request when stream are queued*/
+#define PR_O2_USE_SBUF_L7_RETRY 0x10000000 /* use small buffer for request when L7 retires are enabled */
+#define PR_O2_USE_SBUF_CHECK    0x20000000 /* use small buffer for request's healthchecks */
+#define PR_O2_USE_SBUF_ALL      0x38000000 /* all flags for use-large-buffer option */
+/* unused : 0x40000000 ... 0x80000000 */
 /* end of proxy->options2 */
 
 /* bits for proxy->options3 */
index 76d6b6f91bf2da8b4f8f17f151408233e0c3c52d..1b28fbd8e7c03a086feaf821db94cbce710e26c7 100644 (file)
@@ -2200,6 +2200,42 @@ stats_error_parsing:
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
+               else if (strcmp(args[1], "use-small-buffers") == 0) {
+                       unsigned int flags = PR_O2_USE_SBUF_ALL;
+
+                       if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
+                               err_code |= ERR_WARN;
+                               goto out;
+                       }
+
+                       if (*(args[2])) {
+                               int cur_arg;
+
+                               flags = 0;
+                               for (cur_arg = 2; *(args[cur_arg]); cur_arg++) {
+                                       if (strcmp(args[cur_arg], "queue") == 0)
+                                               flags |= PR_O2_USE_SBUF_QUEUE;
+                                       else if (strcmp(args[cur_arg], "l7-retries") == 0)
+                                               flags |= PR_O2_USE_SBUF_L7_RETRY;
+                                       else if (strcmp(args[cur_arg], "check") == 0)
+                                               flags |= PR_O2_USE_SBUF_CHECK;
+                                       else {
+                                               ha_alert("parsing [%s:%d] : invalid parameter '%s'. option '%s' expects 'queue', 'l7-retries' or 'check' value.\n",
+                                                        file, linenum, args[cur_arg], args[1]);
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
+                                       }
+                               }
+                       }
+                       if (kwm == KWM_STD) {
+                               curproxy->options2 &= ~PR_O2_USE_SBUF_ALL;
+                               curproxy->options2 |= flags;
+                       }
+                       else if (kwm == KWM_NO) {
+                               curproxy->options2 &= ~flags;
+                       }
+                       goto out;
+               }
 
                if (kwm != KWM_STD) {
                        ha_alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
index f89769e6daba7c17b62a6795c0c1e775cf38f3e1..45ada607c548e5f90211fba3df0ead4bb31186e8 100644 (file)
@@ -1685,7 +1685,8 @@ static int start_checks()
         */
        for (px = proxies_list; px; px = px->next) {
                for (s = px->srv; s; s = s->next) {
-                       if (s->check.tcpcheck_rules->flags & TCPCHK_RULES_MAY_USE_SBUF)
+                       if ((px->options2 & PR_O2_USE_SBUF_CHECK) &&
+                           (s->check.tcpcheck_rules->flags & TCPCHK_RULES_MAY_USE_SBUF))
                                s->check.state |= CHK_ST_USE_SMALL_BUFF;
 
                        if (s->check.state & CHK_ST_CONFIGURED) {
index 84ceb0841ba9380f643e5f38c22566ee140e41f3..9f5575d4f577540b1ac77f02f0981ee78342168e 100644 (file)
@@ -1496,7 +1496,8 @@ int sc_conn_send(struct stconn *sc)
                        if (s->txn->req.msg_state != HTTP_MSG_DONE || b_is_large(&oc->buf))
                                s->txn->flags &= ~TX_L7_RETRY;
                        else {
-                               if (!htx_copy_to_small_buffer(&s->txn->l7_buffer, &oc->buf)) {
+                               if (!(s->be->options2 & PR_O2_USE_SBUF_L7_RETRY) ||
+                                   !htx_copy_to_small_buffer(&s->txn->l7_buffer, &oc->buf)) {
                                        if (b_alloc(&s->txn->l7_buffer, DB_UNLIKELY) == NULL)
                                                s->txn->flags &= ~TX_L7_RETRY;
                                        else {
index 8886763bf18d2ef6471b4783baf6475409006639..a83a4f68eb74c21ddb4767c201d1aab3d063c0d9 100644 (file)
@@ -2512,7 +2512,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                        if (scb->state == SC_ST_ASS && srv && srv->rdr_len && (s->flags & SF_REDIRECTABLE))
                                http_perform_server_redirect(s, scb);
 
-                       if (unlikely(scb->state == SC_ST_QUE)) {
+                       if (unlikely((s->be->options2 & PR_O2_USE_SBUF_QUEUE) && scb->state == SC_ST_QUE)) {
                                struct buffer sbuf = BUF_NULL;
 
                                if (IS_HTX_STRM(s)) {