From: Willy Tarreau Date: Mon, 6 Jan 2025 17:55:48 +0000 (+0100) Subject: MINOR: cpu-topo: fall back to nominal_perf and scaling_max_freq for the capacity X-Git-Tag: v3.2-dev8~67 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d11241b7ba936ff823016cd2e6096822af58a46f;p=thirdparty%2Fhaproxy.git MINOR: cpu-topo: fall back to nominal_perf and scaling_max_freq for the capacity 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. --- diff --git a/src/cpu_topo.c b/src/cpu_topo.c index d93940895..47a97aea6 100644 --- a/src/cpu_topo.c +++ b/src/cpu_topo.c @@ -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 */