]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cpu-topo: fall back to nominal_perf and scaling_max_freq for the capacity
authorWilly Tarreau <w@1wt.eu>
Mon, 6 Jan 2025 17:55:48 +0000 (18:55 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 14 Mar 2025 17:30:30 +0000 (18:30 +0100)
When cpu_capacity is not present, let's try to check acpi_cppc's
nominal_perf which is similar and commonly found on servers, then
scaling_max_freq (though that last one may vary a bit between CPUs
depending on die quality). That variation is not a problem since
we can absorb a ~5% variation without issue.

It was verified on an i9-14900 featuring 5.7-P, 6.0-P and 4.4-E GHz
that P-cores were not reordered and that E cores were placed last.
It was also OK on a W3-2345 with 4.3 to 4.5GHz.

src/cpu_topo.c

index d93940895618a187ab89013fc8e06efc35593c53..47a97aea61e69af317e73b6a30b764b2d74ca053 100644 (file)
@@ -406,6 +406,30 @@ int cpu_detect_topology(void)
                        if (trash.data)
                                ha_cpu_topo[cpu].capa = str2uic(trash.area);
                }
+
+               /* When cpu_capacity is not available, sometimes acpi_cppc is
+                * available on servers to provide an equivalent metric allowing
+                * to distinguish big from small cores. Values as low as 15 and
+                * as high as 260 were seen there. Note that only nominal_perf
+                * is trustable, as nominal_freq may return zero. It's also
+                * more reliable than the max cpufreq values because it doesn't
+                * seem to take into account the die quality.
+                */
+               if (ha_cpu_topo[cpu].capa < 0 &&
+                   read_line_to_trash(NUMA_DETECT_SYSTEM_SYSFS_PATH "/cpu/cpu%d/acpi_cppc/nominal_perf", cpu) >= 0) {
+                       if (trash.data)
+                               ha_cpu_topo[cpu].capa = str2uic(trash.area);
+               }
+
+               /* Finally if none of them is available we can have a look at
+                * cpufreq's max cpu frequency.
+                */
+               if (ha_cpu_topo[cpu].capa < 0 &&
+                   read_line_to_trash(NUMA_DETECT_SYSTEM_SYSFS_PATH "/cpu/cpu%d/cpufreq/scaling_max_freq", cpu) >= 0) {
+                       /* This is in kHz turn it to MHz to stay below 32k */
+                       if (trash.data)
+                               ha_cpu_topo[cpu].capa = (str2uic(trash.area) + 999U) / 1000U;
+               }
        }
 
        /* Now locate NUMA node IDs if any */