]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: threads: detect excessive thread counts vs cpu-map
authorWilly Tarreau <w@1wt.eu>
Mon, 4 Sep 2023 15:36:20 +0000 (17:36 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 4 Sep 2023 17:39:17 +0000 (19:39 +0200)
This detects when there are more threads bound via cpu-map than CPUs
enabled in cpu-map, or when there are more total threads than the total
number of CPUs available at boot (for unbound threads) and configured
for bound threads. In this case, a warning is emitted to explain the
problems it will cause, and explaining how to address the situation.

Note that some configurations will not be detected as faulty because
the algorithmic complexity to resolve all arrangements grows in O(N!).
This means that having 3 threads on 2 CPUs and one thread on 2 CPUs
will not be detected as it's 4 threads for 4 CPUs. But at least configs
such as T0:(1,4) T1:(1,4) T2:(2,4) T3:(3,4) will not trigger a warning
since they're valid.

include/haproxy/thread.h
src/haproxy.c
src/thread.c

index 97bb4f4faf3334e9588862487f599971832104ec..df3c17bc37ef6f8bcbc6345923e1f8cc1718acd5 100644 (file)
@@ -44,6 +44,7 @@ void ha_tkill(unsigned int thr, int sig);
 void ha_tkillall(int sig);
 void ha_thread_relax(void);
 int thread_detect_binding_discrepancies(void);
+int thread_detect_more_than_cpus(void);
 int thread_map_to_groups();
 int thread_resolve_group_mask(struct thread_set *ts, int defgrp, char **err);
 int parse_thread_set(const char *arg, struct thread_set *ts, char **err);
index 7d5ddba60275d53f196e06077a714624d4267c74..06b988dad28930449e9752dab563547c0492cd19 100644 (file)
@@ -2311,6 +2311,7 @@ static void init(int argc, char **argv)
 #endif
 
        thread_detect_binding_discrepancies();
+       thread_detect_more_than_cpus();
 
        /* Apply server states */
        apply_server_state();
index 203150af05750ea0ecd42b4635c72652ac212585..6c3eddd366a0ff92b29c8e576a91001ceb7b91bd 100644 (file)
@@ -1171,6 +1171,62 @@ int thread_detect_binding_discrepancies(void)
        return 0;
 }
 
+/* Returns non-zero on anomaly (more threads than CPUs), and emits a warning in
+ * this case. It checks against configured cpu-map if any, otherwise against
+ * the number of CPUs at boot if known. It's better to run it only after
+ * thread_detect_binding_discrepancies() so that mixed cases can be eliminated.
+ */
+int thread_detect_more_than_cpus(void)
+{
+#if defined(USE_CPU_AFFINITY)
+       struct hap_cpuset cpuset_map, cpuset_boot, cpuset_all;
+       uint th, tg, id;
+       int bound;
+       int tot_map, tot_all;
+
+       ha_cpuset_zero(&cpuset_boot);
+       ha_cpuset_zero(&cpuset_map);
+       ha_cpuset_zero(&cpuset_all);
+       bound = 0;
+       for (th = 0; th < global.nbthread; th++) {
+               tg = ha_thread_info[th].tgid;
+               id = ha_thread_info[th].ltid;
+               if (ha_cpuset_count(&cpu_map[tg - 1].thread[id])) {
+                       ha_cpuset_or(&cpuset_map, &cpu_map[tg - 1].thread[id]);
+                       bound++;
+               }
+       }
+
+       ha_cpuset_assign(&cpuset_all, &cpuset_map);
+       if (bound != global.nbthread) {
+               if (ha_cpuset_detect_bound(&cpuset_boot))
+                       ha_cpuset_or(&cpuset_all, &cpuset_boot);
+       }
+
+       tot_map = ha_cpuset_count(&cpuset_map);
+       tot_all = ha_cpuset_count(&cpuset_all);
+
+       if (tot_map && bound > tot_map) {
+               ha_warning("This configuration binds %d threads to a total of %d CPUs via cpu-map "
+                          "directives. This means that some threads will compete for the same CPU, "
+                          "which will cause severe performance degradation. Please fix either the "
+                          "'cpu-map' directives or set the global 'nbthread' value accordingly.\n",
+                          bound, tot_map);
+               return 1;
+       }
+       else if (tot_all && global.nbthread > tot_all) {
+               ha_warning("This configuration enables %d threads running on a total of %d CPUs. "
+                          "This means that some threads will compete for the same CPU, which will cause "
+                          "severe performance degradation. Please either the 'cpu-map' directives to "
+                          "adjust the CPUs to use, or fix the global 'nbthread' value.\n",
+                          global.nbthread, tot_all);
+               return 1;
+       }
+#endif
+       return 0;
+}
+
+
 /* scans the configured thread mapping and establishes the final one. Returns <0
  * on failure, >=0 on success.
  */