From: Willy Tarreau Date: Tue, 10 Feb 2026 15:57:55 +0000 (+0100) Subject: MINOR: activity: allow to switch per-task lock/memory profiling at runtime X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c724693b952be6f85de26cf507278782066bc2d8;p=thirdparty%2Fhaproxy.git MINOR: activity: allow to switch per-task lock/memory profiling at runtime 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. --- diff --git a/doc/management.txt b/doc/management.txt index aacbfab6c..cee9f5b56 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -2558,7 +2558,8 @@ set maxconn global 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 Change the process-wide connection rate limit, which is set by the global 'maxconnrate' setting. A value of zero disables the limitation. This limit diff --git a/src/activity.c b/src/activity.c index 8f794abb1..0c1ce9e6b 100644 --- a/src/activity.c +++ b/src/activity.c @@ -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; }