From: Willy Tarreau Date: Fri, 14 Mar 2025 16:06:00 +0000 (+0100) Subject: MINOR: cpu-topo: boost the capacity of performance cores with cpufreq X-Git-Tag: v3.2-dev8~65 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c5ddf4a5b2a466cf19c5df63ef58baa907c292a4;p=thirdparty%2Fhaproxy.git MINOR: cpu-topo: boost the capacity of performance cores with cpufreq Cpufreq alone isn't a good metric on heterogenous CPUs because efficient cores can reach almost as high frequencies as performant ones. Tests have shown that majoring performance cores by 50% gives a pretty accurate estimate of the performance to expect on modern CPUs, and that counting +33% per extra SMT thread is reasonable as well. We don't have the info about the core's quality, but using the presence of SMT is a reasonable approach in this case, given that efficiency cores will not use it. As an example, using one thread of each of the 8 P-cores of an intel i9-14900k gives 395k rps for a corrected total capacity of 69.3k, using the 16 E-cores gives 40.5k for a total capacity of 70.4k, and using both threads of 6 P-cores gives 41.1k for a total capacity of 69.6k. Thus the 3 same scores deliver the same performance in various combinations. --- diff --git a/src/cpu_topo.c b/src/cpu_topo.c index 3a7253e51..d59c0c888 100644 --- a/src/cpu_topo.c +++ b/src/cpu_topo.c @@ -419,13 +419,20 @@ int cpu_detect_topology(void) * start just due to this. Thus we start with cpufreq and fall * back to acpi_cppc. If it becomes an issue, we could imagine * forcing the value to all members of the same core and even - * cluster. + * cluster. Since the frequency alone is not a good criterion + * to qualify the CPU quality (perf vs efficiency core), instead + * we rely on the thread count to gauge if it's a performant or + * an efficient core, and we major performant cores' capacity + * by 50% (shown to be roughly correct on modern CPUs). */ 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) + if (trash.data) { ha_cpu_topo[cpu].capa = (str2uic(trash.area) + 999U) / 1000U; + if (ha_cpu_topo[cpu].th_cnt > 1) + ha_cpu_topo[cpu].capa = ha_cpu_topo[cpu].capa * 3 / 2; + } } if (ha_cpu_topo[cpu].capa < 0 &&