]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: activity: allow to switch per-task lock/memory profiling at runtime
authorWilly Tarreau <w@1wt.eu>
Tue, 10 Feb 2026 15:57:55 +0000 (16:57 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 10 Feb 2026 16:53:01 +0000 (17:53 +0100)
Given that we already have "set profiling task", it's easy to permit to
enable/disable the lock and/or memory profiling at run time. However, the
change will only be applied next time the task profiling will be switched
from off/auto to on.

The patch is very minor and is best viewed with git show -b because it
indents a whole block that moves in a "if" clause.

This can be backported to 3.3 along with the two previous patches.

doc/management.txt
src/activity.c

index aacbfab6c8a354244f632870a4a5f869fc2ef70c..cee9f5b56fe5b9a0ce35d8efb90ed490bc33f7e6 100644 (file)
@@ -2558,7 +2558,8 @@ set maxconn global <maxconn>
   delayed until the threshold is reached. A value of zero restores the initial
   setting.
 
-set profiling { tasks | memory } { auto | on | off }
+set profiling memory { on | off }
+set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }
   Enables or disables CPU or memory profiling for the indicated subsystem. This
   is equivalent to setting or clearing the "profiling" settings in the "global"
   section of the configuration file. Please also see "show profiling". Note
@@ -2568,6 +2569,13 @@ set profiling { tasks | memory } { auto | on | off }
   on the linux-glibc target), and requires USE_MEMORY_PROFILING to be set at
   compile time.
 
+. For tasks profiling, it is possible to enable or disable the collection of
+  per-task lock and memory timings at runtime, but the change is only taken
+  into account next time the profiler switches from off/auto to on (either
+  automatically or manually). Thus when using "no-lock" to disable per-task
+  lock profiling and save CPU cycles, it is recommended to flip the task
+  profiling off then on to commit the change.
+
 set rate-limit connections global <value>
   Change the process-wide connection rate limit, which is set by the global
   'maxconnrate' setting. A value of zero disables the limitation. This limit
index 8f794abb146f9a79fcbcfc8b849e2086ffb46d80..0c1ce9e6bffc40ac88e946160c079a55778cbfcf 100644 (file)
@@ -747,6 +747,8 @@ static int cfg_parse_prof_tasks(char **args, int section_type, struct proxy *cur
 /* parse a "set profiling" command. It always returns 1. */
 static int cli_parse_set_profiling(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       int arg;
+
        if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
                return 1;
 
@@ -792,52 +794,66 @@ static int cli_parse_set_profiling(char **args, char *payload, struct appctx *ap
        if (strcmp(args[2], "tasks") != 0)
                return cli_err(appctx, "Expects either 'tasks' or 'memory'.\n");
 
-       if (strcmp(args[3], "on") == 0) {
-               unsigned int old = profiling;
-               int i;
-
-               while (!_HA_ATOMIC_CAS(&profiling, &old, (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_ON))
-                       ;
-
-               HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
-               HA_ATOMIC_STORE(&prof_task_stop_ns, 0);
-
-               /* also flush current profiling stats */
-               for (i = 0; i < SCHED_ACT_HASH_BUCKETS; i++) {
-                       HA_ATOMIC_STORE(&sched_activity[i].calls, 0);
-                       HA_ATOMIC_STORE(&sched_activity[i].cpu_time, 0);
-                       HA_ATOMIC_STORE(&sched_activity[i].lat_time, 0);
-                       HA_ATOMIC_STORE(&sched_activity[i].lkw_time, 0);
-                       HA_ATOMIC_STORE(&sched_activity[i].lkd_time, 0);
-                       HA_ATOMIC_STORE(&sched_activity[i].mem_time, 0);
-                       HA_ATOMIC_STORE(&sched_activity[i].func, NULL);
-                       HA_ATOMIC_STORE(&sched_activity[i].caller, NULL);
+       for (arg = 3; *args[arg]; arg++) {
+               if (strcmp(args[arg], "on") == 0) {
+                       unsigned int old = profiling;
+                       int i;
+
+                       while (!_HA_ATOMIC_CAS(&profiling, &old, (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_ON))
+                               ;
+
+                       HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
+                       HA_ATOMIC_STORE(&prof_task_stop_ns, 0);
+
+                       /* also flush current profiling stats */
+                       for (i = 0; i < SCHED_ACT_HASH_BUCKETS; i++) {
+                               HA_ATOMIC_STORE(&sched_activity[i].calls, 0);
+                               HA_ATOMIC_STORE(&sched_activity[i].cpu_time, 0);
+                               HA_ATOMIC_STORE(&sched_activity[i].lat_time, 0);
+                               HA_ATOMIC_STORE(&sched_activity[i].lkw_time, 0);
+                               HA_ATOMIC_STORE(&sched_activity[i].lkd_time, 0);
+                               HA_ATOMIC_STORE(&sched_activity[i].mem_time, 0);
+                               HA_ATOMIC_STORE(&sched_activity[i].func, NULL);
+                               HA_ATOMIC_STORE(&sched_activity[i].caller, NULL);
+                       }
                }
-       }
-       else if (strcmp(args[3], "auto") == 0) {
-               unsigned int old = profiling;
-               unsigned int new;
+               else if (strcmp(args[arg], "auto") == 0) {
+                       unsigned int old = profiling;
+                       unsigned int new;
 
-               do {
-                       if ((old & HA_PROF_TASKS_MASK) >= HA_PROF_TASKS_AON)
-                               new = (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AON;
-                       else
-                               new = (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AOFF;
-               } while (!_HA_ATOMIC_CAS(&profiling, &old, new));
+                       do {
+                               if ((old & HA_PROF_TASKS_MASK) >= HA_PROF_TASKS_AON)
+                                       new = (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AON;
+                               else
+                                       new = (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AOFF;
+                       } while (!_HA_ATOMIC_CAS(&profiling, &old, new));
 
-               HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
-               HA_ATOMIC_STORE(&prof_task_stop_ns, 0);
-       }
-       else if (strcmp(args[3], "off") == 0) {
-               unsigned int old = profiling;
-               while (!_HA_ATOMIC_CAS(&profiling, &old, (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_OFF))
-                       ;
+                       HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
+                       HA_ATOMIC_STORE(&prof_task_stop_ns, 0);
+               }
+               else if (strcmp(args[arg], "off") == 0) {
+                       unsigned int old = profiling;
+                       while (!_HA_ATOMIC_CAS(&profiling, &old, (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_OFF))
+                               ;
 
-               if (HA_ATOMIC_LOAD(&prof_task_start_ns))
-                       HA_ATOMIC_STORE(&prof_task_stop_ns, now_ns);
+                       if (HA_ATOMIC_LOAD(&prof_task_start_ns))
+                               HA_ATOMIC_STORE(&prof_task_stop_ns, now_ns);
+               }
+               else if (strcmp(args[arg], "lock") == 0)
+                       HA_ATOMIC_OR(&profiling, HA_PROF_TASKS_LOCK);
+               else if (strcmp(args[arg], "no-lock") == 0)
+                       HA_ATOMIC_AND(&profiling, ~HA_PROF_TASKS_LOCK);
+               else if (strcmp(args[arg], "memory") == 0)
+                       HA_ATOMIC_OR(&profiling, HA_PROF_TASKS_MEM);
+               else if (strcmp(args[arg], "no-memory") == 0)
+                       HA_ATOMIC_AND(&profiling, ~HA_PROF_TASKS_MEM);
+               else
+                       break; // unknown arg
        }
-       else
-               return cli_err(appctx, "Expects 'on', 'auto', or 'off'.\n");
+
+       /* either no arg or invalid one */
+       if (arg == 3 || *args[arg])
+               return cli_err(appctx, "Expects a combination of either 'on', 'auto', 'off', 'lock', 'no-lock', 'memory' or 'no-memory'.\n");
 
        return 1;
 }