diff --git a/shell/services/SystemStats.qml b/shell/services/SystemStats.qml index 7345727..b2c67f0 100644 --- a/shell/services/SystemStats.qml +++ b/shell/services/SystemStats.qml @@ -122,10 +122,10 @@ QtObject { } } - // One-time: per-core max freq + // One-time: per-core max freq (numerically sorted) property var _maxFreqProc: Process { running: true - command: ["sh", "-c", "for f in /sys/devices/system/cpu/cpu[0-9]*/cpufreq/cpuinfo_max_freq; do [ -f \"$f\" ] && cat \"$f\" || echo 0; done 2>/dev/null"] + command: ["sh", "-c", "ls -d /sys/devices/system/cpu/cpu[0-9]* 2>/dev/null | sort -V | while read d; do f=\"$d/cpufreq/cpuinfo_max_freq\"; [ -f \"$f\" ] && cat \"$f\" || echo 0; done"] stdout: StdioCollector { onStreamFinished: { root.cpuCoreMaxFreq = text.trim().split("\n").filter(l => l).map(l => parseInt(l) / 1e6); @@ -134,16 +134,79 @@ QtObject { } // One-time: P/E-core topology + // Priority: cpu_core/cpu_atom sysfs > topology/core_type > freq-gap heuristic property var _coreTypesProc: Process { running: true - command: ["sh", "-c", "for d in /sys/devices/system/cpu/cpu[0-9]*/topology/core_type; do [ -f \"$d\" ] && cat \"$d\" || echo Performance; done 2>/dev/null"] + command: ["sh", "-c", String.raw` + # Intel hybrid: /sys/devices/cpu_core/cpus and cpu_atom/cpus give CPU ranges + if [ -f /sys/devices/cpu_core/cpus ] && [ -f /sys/devices/cpu_atom/cpus ]; then + core=$(cat /sys/devices/cpu_core/cpus) + atom=$(cat /sys/devices/cpu_atom/cpus) + echo "hybrid:$core:$atom" + exit 0 + fi + # Fallback: per-core topology/core_type + ls -d /sys/devices/system/cpu/cpu[0-9]* 2>/dev/null | sort -V | while read d; do + f="$d/topology/core_type" + [ -f "$f" ] && cat "$f" + done + `] stdout: StdioCollector { onStreamFinished: { - root.cpuCoreTypes = text.trim().split("\n").filter(l => l).map(l => l.trim()); + const out = text.trim(); + if (!out) + return; + if (out.startsWith("hybrid:")) { + // Parse cpu_core/cpu_atom ranges into per-cpu type array + const parts = out.split(":"); + const coreRange = parts[1]; + const atomRange = parts[2]; + function expandRange(s) { + const cpus = new Set(); + for (const part of s.split(",")) { + if (part.includes("-")) { + const [a, b] = part.split("-").map(Number); + for (let i = a; i <= b; i++) + cpus.add(i); + } else { + cpus.add(Number(part)); + } + } + return cpus; + } + const pCores = expandRange(coreRange); + const eCores = expandRange(atomRange); + const maxCpu = Math.max(...pCores, ...eCores); + const types = []; + for (let i = 0; i <= maxCpu; i++) + types.push(eCores.has(i) ? "Efficiency" : "Performance"); + root.cpuCoreTypes = types; + } else { + // topology/core_type output + const types = out.split("\n").filter(l => l).map(l => l.trim()); + if (types.length > 0) + root.cpuCoreTypes = types; + } } } } + // Fallback: infer P/E from max freq gap when no sysfs topology is available + function _inferCoreTypesFromFreq() { + if (cpuCoreTypes.length > 0 || cpuCoreMaxFreq.length < 2) + return; + const freqs = cpuCoreMaxFreq.filter(f => f > 0); + if (!freqs.length) + return; + const maxF = Math.max(...freqs); + const minF = Math.min(...freqs); + if (maxF > 0 && minF > 0 && (maxF - minF) / maxF > 0.15) { + const threshold = (maxF + minF) / 2; + cpuCoreTypes = cpuCoreMaxFreq.map(f => f >= threshold ? "Performance" : "Efficiency"); + } + } + onCpuCoreMaxFreqChanged: Qt.callLater(_inferCoreTypesFromFreq) + // Disk via df property var _diskProc: Process { id: diskProc