From: Amaury Denoyelle Date: Fri, 26 Mar 2021 17:50:33 +0000 (+0100) Subject: MINOR: global: add option to disable numa detection X-Git-Tag: v2.4-dev17~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0f50cb9c732ff085bc274f6db5116a6d600375cb;p=thirdparty%2Fhaproxy.git MINOR: global: add option to disable numa detection Render numa detection optional with a global configuration statement 'no numa-cpu-mapping'. This can be used if the applied affinity of the algorithm is not optimal. Also complete the documentation with this new keyword. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index c50700f124..8827f9bb7f 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -919,6 +919,7 @@ The following keywords are supported in the "global" section : - nbproc - nbthread - node + - numa-cpu-mapping - pidfile - pp2-never-send-local - presetenv @@ -1540,6 +1541,17 @@ nbthread like "taskset" or "cpuset". Otherwise, this value defaults to 1. The default value is reported in the output of "haproxy -vv". See also "nbproc". +numa-cpu-mapping + By default, if running on Linux, haproxy inspects on startup the CPU topology + of the machine. If a multi-socket machine is detected, the affinity is + automatically calculated to run on the CPUs of a single node. This is done in + order to not suffer from the performance penalties caused by the inter-socket + bus latency. However, if the applied binding is non optimal on a particular + architecture, it can be disabled with the statement 'no numa-cpu-mapping'. + This automatic binding is also not applied if a nbthread statement is present + in the configuration, or the affinity of the process is already specified, + for example via the 'cpu-map' directive or the taskset utility. + pidfile Writes PIDs of all daemons into file when daemon mode or writes PID of master process into file when master-worker mode. This option is diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index bc734a6d02..03a6a50309 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -166,6 +166,7 @@ struct global { struct hap_cpuset thread[MAX_THREADS]; /* list of CPU masks for the 32/64 first threads of the 1st process */ } cpu_map; #endif + int numa_cpu_mapping; /* The info above is config stuff, it doesn't change during the process' life */ /* A number of the elements below are updated by all threads in real time and * suffer high contention, so we need to put them in their own cache lines, if diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c index 89e3b10b0a..47de32a6b1 100644 --- a/src/cfgparse-global.c +++ b/src/cfgparse-global.c @@ -42,7 +42,8 @@ static const char *common_kw_list[] = { "log-send-hostname", "server-state-base", "server-state-file", "log-tag", "spread-checks", "max-spread-checks", "cpu-map", "setenv", "presetenv", "unsetenv", "resetenv", "strict-limits", "localpeer", - "defaults", "listen", "frontend", "backend", "peers", "resolvers", + "numa-cpu-mapping", "defaults", "listen", "frontend", "backend", + "peers", "resolvers", NULL /* must be last */ }; @@ -1288,6 +1289,9 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm) } setenv("HAPROXY_LOCALPEER", localpeer, 1); } + else if (strcmp(args[0], "numa-cpu-mapping") == 0) { + global.numa_cpu_mapping = (kwm == KWM_NO) ? 0 : 1; + } else { struct cfg_kw_list *kwl; const char *best; diff --git a/src/cfgparse.c b/src/cfgparse.c index 25820bc017..507d072fa3 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1846,10 +1846,12 @@ next_line: if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && strcmp(args[0], "log") != 0 && strcmp(args[0], "busy-polling") != 0 && strcmp(args[0], "set-dumpable") != 0 && strcmp(args[0], "strict-limits") != 0 && - strcmp(args[0], "insecure-fork-wanted") != 0) { + strcmp(args[0], "insecure-fork-wanted") != 0 && + strcmp(args[0], "numa-cpu-mapping") != 0) { ha_alert("parsing [%s:%d]: negation/default currently " "supported only for options, log, busy-polling, " - "set-dumpable, strict-limits, and insecure-fork-wanted.\n", file, linenum); + "set-dumpable, strict-limits, insecure-fork-wanted " + "and numa-cpu-mapping.\n", file, linenum); err_code |= ERR_ALERT | ERR_FATAL; fatal++; } @@ -2189,7 +2191,7 @@ int check_config_validity() if (global.nbproc == 1) { int numa_cores = 0; #if defined(__linux__) && defined USE_CPU_AFFINITY - if (!thread_cpu_mask_forced()) + if (global.numa_cpu_mapping && !thread_cpu_mask_forced()) numa_cores = numa_detect_topology(); #endif global.nbthread = numa_cores ? numa_cores : diff --git a/src/haproxy.c b/src/haproxy.c index 58e9e62f9e..b89c51779f 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -160,6 +160,7 @@ volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stoppin struct global global = { .hard_stop_after = TICK_ETERNITY, .nbproc = 1, + .numa_cpu_mapping = 1, .nbthread = 0, .req_count = 0, .logsrvs = LIST_HEAD_INIT(global.logsrvs),