]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: debug: add "rt=1" to "debug dev task" to tune the RT flag
authorWilly Tarreau <w@1wt.eu>
Wed, 24 Jun 2026 15:38:07 +0000 (17:38 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 24 Jun 2026 17:08:08 +0000 (19:08 +0200)
When rt=1 is set, the created task is set to real time. This will
essentially be used jointly with print=1 to print the wakeup date.

Now it is pretty much visible that TASK_RT helps keeping recurrent
delays stable under load:

  $ socat - /tmp/sock1 <<< "expert-mode on;debug dev sched task inter=1 count=100000"
  $ socat - /tmp/sock1 <<< "expert-mode on;debug dev sched task print=1 inter=1000 count=1"

  $ taskset -c 0  ./haproxy -db -f h2-h1.cfg
  [NOTICE]   (11262) : Automatically setting global.maxconn to 2033.
  task 0x5a67740: time_ms=355817139.2593
  task 0x5a67740: time_ms=355818165.934056
  task 0x5a67740: time_ms=355819192.609666
  task 0x5a67740: time_ms=355820219.528467
  task 0x5a67740: time_ms=355821245.778249
  task 0x5a67740: time_ms=355822271.800731
  task 0x5a67740: time_ms=355823297.836419
  task 0x5a67740: time_ms=355824327.894992
  task 0x5a67740: time_ms=355825354.92738
  task 0x5a67740: time_ms=355826381.242925
  ^C
  => ~1030ms interval

  $ socat - /tmp/sock1 <<< "expert-mode on;debug dev sched task inter=1 count=100000"
  $ socat - /tmp/sock1 <<< "expert-mode on;debug dev sched task print=1 inter=1000 count=1 rt=1"

  $ taskset -c 0  ./haproxy -db -f h2-h1.cfg
  [NOTICE]   (11274) : Automatically setting global.maxconn to 2033.
  task 0x1c89d740: time_ms=355842657.804670
  task 0x1c89d740: time_ms=355843657.130495
  task 0x1c89d740: time_ms=355844657.159396
  task 0x1c89d740: time_ms=355845657.176695
  task 0x1c89d740: time_ms=355846657.144914
  task 0x1c89d740: time_ms=355847657.416217
  task 0x1c89d740: time_ms=355848657.192072
  ^C
  => ~1000ms interval

Also mixing one non-rt and one rt tasks easily shows that the non-RT skews:

  task 0x3180080: time_ms=356074147.738657
  task 0x7f82705749c0: time_ms=356074167.140429
  task 0x3180080: time_ms=356075157.58365
  task 0x7f82705749c0: time_ms=356075167.155128
  task 0x3180080: time_ms=356076167.23508
  task 0x7f82705749c0: time_ms=356076167.163529
  task 0x7f82705749c0: time_ms=356077167.131421
  task 0x3180080: time_ms=356077176.204301
  task 0x7f82705749c0: time_ms=356078167.172336
  task 0x3180080: time_ms=356078186.76828
  task 0x7f82705749c0: time_ms=356079167.110302
  task 0x3180080: time_ms=356079195.814623

Under traffic with a run queue of 50k, with non-rt we can see delays
of up to a few hundred ms, while the rt one is stable:

  task 0xf52228e3c580: time_ms=12817821323.738291
  task 0xf52228e3c580: time_ms=12817822375.954267
  task 0xf52228e3c580: time_ms=12817823437.542732
  task 0xf522c85fe340: time_ms=12817823901.552931
  task 0xf52228e3c580: time_ms=12817824487.769129
  task 0xf522c85fe340: time_ms=12817824901.491252
  task 0xf52228e3c580: time_ms=12817825553.539234
  task 0xf522c85fe340: time_ms=12817825901.930177
  task 0xf52228e3c580: time_ms=12817826613.611365
  task 0xf522c85fe340: time_ms=12817826901.94851
  task 0xf52228e3c580: time_ms=12817827659.386720
  task 0xf522c85fe340: time_ms=12817827901.655777
  task 0xf52228e3c580: time_ms=12817828694.795097
  task 0xf522c85fe340: time_ms=12817828901.882341
  task 0xf52228e3c580: time_ms=12817829765.216886
  task 0xf522c85fe340: time_ms=12817829901.723780
  task 0xf52228e3c580: time_ms=12817830844.706481
  task 0xf522c85fe340: time_ms=12817830901.571820
  task 0xf522c85fe340: time_ms=12817831901.440380
  task 0xf52228e3c580: time_ms=12817831951.556375

This indicates that thisshould be a sufficient first step to unblock
haload.

src/debug.c

index afb90429803d681072734c09ebeb32da81c8ae5c..ebc251a7f4e0459f2d350b61d7da2d6a826fccfe 100644 (file)
@@ -1716,7 +1716,7 @@ static struct task *debug_tasklet_handler(struct task *t, void *ctx, unsigned in
 }
 
 /* parse a "debug dev sched" command
- * debug dev sched {task|tasklet} [count=<count>] [mask=<mask>] [single=<single>] [inter=<inter>] [print=<print>]
+ * debug dev sched {task|tasklet} [count=<count>] [mask=<mask>] [single=<single>] [inter=<inter>] [print=<print>] [rt=<rt>]
  */
 static int debug_parse_cli_sched(char **args, char *payload, struct appctx *appctx, void *private)
 {
@@ -1732,6 +1732,7 @@ static int debug_parse_cli_sched(char **args, char *payload, struct appctx *appc
        unsigned long thrid = tid;
        unsigned int inter = 0;
        unsigned int print = 0;
+       unsigned int rt = 0;
        unsigned long i;
        int mode = 0; // 0 = tasklet; 1 = task
        unsigned long *tctx; // [0] = #tasks, [1] = inter, [2+] = { tl | (tsk+1) }
@@ -1744,7 +1745,7 @@ static int debug_parse_cli_sched(char **args, char *payload, struct appctx *appc
        if (strcmp(args[3], "task") != 0 && strcmp(args[3], "tasklet") != 0) {
                return cli_err(appctx,
                               "Usage: debug dev sched {task|tasklet} { <obj> = <value> }*\n"
-                              "     <obj>   = {count | tid | inter | print }\n"
+                              "     <obj>   = {count | tid | inter | print | rt }\n"
                               "     <value> = 64-bit dec/hex integer (0x prefix supported)\n"
                               );
        }
@@ -1765,6 +1766,8 @@ static int debug_parse_cli_sched(char **args, char *payload, struct appctx *appc
                        ptr = &inter; size = sizeof(inter);
                } else if (isteq(name, ist("print"))) {
                        ptr = &print; size = sizeof(print);
+               } else if (isteq(name, ist("rt"))) {
+                       ptr = &rt; size = sizeof(rt);
                } else
                        return cli_dynerr(appctx, memprintf(&msg, "Unsupported setting: '%s'.\n", word));
 
@@ -1831,7 +1834,7 @@ static int debug_parse_cli_sched(char **args, char *payload, struct appctx *appc
 
                if (ctx & 1)
                        task_wakeup((struct task *)(ctx - 1),
-                                   TASK_WOKEN_INIT | (print ? TASK_F_USR1 : 0));
+                                   TASK_WOKEN_INIT | (print ? TASK_F_USR1 : 0) | (rt ? TASK_RT : 0));
                else
                        tasklet_wakeup((struct tasklet *)ctx);
        }