Battery: fix hardware nominal frequency, separate it from max boost
cpuinfo_max_freq is the highest boost state, not the base clock - mislabeling it "nominal" understated the gap between the two on an AMD box using acpi-cpufreq (this machine: 5.08 GHz boost vs 3.40 GHz base). Prefer, in order: the model-name string, cpufreq's own base_frequency (intel_pstate, kHz), ACPI CPPC's nominal_freq (MHz; what acpi-cpufreq exposes instead), else "unknown". cpuinfo_max_freq is now reported alongside, separately, as "max boost", never folded into "nominal". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+24
-10
@@ -203,18 +203,30 @@ def linux_hardware():
|
||||
sockets.add(p.group(1))
|
||||
cores.add((p.group(1), c.group(1)))
|
||||
|
||||
# Nominal (base) clock, never the boost clock: the model-name string, else cpufreq's own
|
||||
# base_frequency (intel_pstate, kHz), else ACPI CPPC's nominal_freq (MHz; what AMD's
|
||||
# acpi-cpufreq exposes instead - cpuinfo_max_freq on those boxes is the boost clock, not this).
|
||||
freq_ghz, freq_source = None, "unknown"
|
||||
m = re.search(r"@\s*([\d.]+)\s*GHz", model or "")
|
||||
if m:
|
||||
freq_ghz, freq_source = float(m.group(1)), "model name"
|
||||
else:
|
||||
for name in ("base_frequency", "cpuinfo_max_freq"):
|
||||
try:
|
||||
freq_ghz = int(open("/sys/devices/system/cpu/cpu0/cpufreq/base_frequency").read()) / 1e6
|
||||
freq_source = "base_frequency"
|
||||
except (OSError, ValueError):
|
||||
try:
|
||||
freq_ghz = int(open(f"/sys/devices/system/cpu/cpu0/cpufreq/{name}").read()) / 1e6
|
||||
freq_source = name
|
||||
break
|
||||
freq_ghz = int(open("/sys/devices/system/cpu/cpu0/acpi_cppc/nominal_freq").read()) / 1e3
|
||||
freq_source = "acpi_cppc"
|
||||
except (OSError, ValueError):
|
||||
continue
|
||||
pass
|
||||
|
||||
# Reported separately, and never as "nominal": cpuinfo_max_freq is the highest boost state.
|
||||
max_boost_ghz = None
|
||||
try:
|
||||
max_boost_ghz = int(open("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq").read()) / 1e6
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
|
||||
mem_gib = None
|
||||
try:
|
||||
@@ -226,8 +238,9 @@ def linux_hardware():
|
||||
pass
|
||||
|
||||
return {"cpu_model": model or "unknown", "cpu_base_ghz": freq_ghz, "cpu_base_source": freq_source,
|
||||
"sockets": len(sockets) or None, "physical_cores": len(cores) or None,
|
||||
"threads": os.cpu_count(), "memory_gib": mem_gib, "gpus": gpu_hardware()}
|
||||
"cpu_max_boost_ghz": max_boost_ghz, "sockets": len(sockets) or None,
|
||||
"physical_cores": len(cores) or None, "threads": os.cpu_count(), "memory_gib": mem_gib,
|
||||
"gpus": gpu_hardware()}
|
||||
|
||||
|
||||
def macos_hardware():
|
||||
@@ -246,15 +259,16 @@ def macos_hardware():
|
||||
cores = f"{p_cores}P+{e_cores}E"
|
||||
mem = sysctl("hw.memsize")
|
||||
return {"cpu_model": model or "unknown", "cpu_base_ghz": freq_ghz, "cpu_base_source": freq_source,
|
||||
"sockets": int(sysctl("hw.packages") or 1), "physical_cores": cores,
|
||||
"cpu_max_boost_ghz": None, "sockets": int(sysctl("hw.packages") or 1), "physical_cores": cores,
|
||||
"threads": int(sysctl("hw.logicalcpu") or os.cpu_count()),
|
||||
"memory_gib": int(mem) / 1024 ** 3 if mem else None, "gpus": []}
|
||||
|
||||
|
||||
def hardware_info():
|
||||
"""The run host's hardware, for the manifest: CPU model, nominal/base frequency (and where it
|
||||
came from), physical cores, threads, sockets, memory, GPUs. Linux is detailed; macOS is a short
|
||||
best-effort; anywhere else this is just empty, and the report says so."""
|
||||
came from) plus max boost frequency separately, physical cores, threads, sockets, memory, GPUs.
|
||||
Linux is detailed; macOS is a short best-effort; anywhere else this is just empty, and the
|
||||
report says so."""
|
||||
try:
|
||||
if sys.platform == "darwin":
|
||||
return macos_hardware()
|
||||
|
||||
@@ -293,8 +293,11 @@ def hardware_line(man):
|
||||
hw = man.get("hardware")
|
||||
if not hw:
|
||||
return "hardware: not recorded"
|
||||
freq = f"{hw['cpu_base_ghz']:.2f} GHz nominal ({hw['cpu_base_source']})" if hw.get("cpu_base_ghz") else \
|
||||
f"nominal frequency unknown ({hw.get('cpu_base_source', 'unknown')})"
|
||||
freq_bits = [f"{hw['cpu_base_ghz']:.2f} GHz nominal ({hw['cpu_base_source']})" if hw.get("cpu_base_ghz")
|
||||
else "nominal frequency unknown"]
|
||||
if hw.get("cpu_max_boost_ghz"):
|
||||
freq_bits.append(f"{hw['cpu_max_boost_ghz']:.2f} GHz max boost")
|
||||
freq = ", ".join(freq_bits)
|
||||
cores = f"{f(hw.get('physical_cores'), '{}')}C/{hw.get('threads') or '?'}T, {f(hw.get('sockets'), '{}')} socket(s)"
|
||||
mem = f"{hw['memory_gib']:.0f} GiB RAM" if hw.get("memory_gib") else "RAM unknown"
|
||||
gpus = ", ".join(f"{g['name']} ({g['memory']})" for g in hw.get("gpus") or []) or "none"
|
||||
|
||||
Reference in New Issue
Block a user