CPU und GPU zwischen Auslastung und Temperatur umschaltbar

Die M-Serie-Konvention gilt auch auf dem M5: Tp* sind die CPU-Kerne, Tg* die
GPU-Cluster. Gezeigt wird der wärmste Punkt, nicht der Durchschnitt —
gedrosselt wird nach dem heißesten Kern. Gemessen: CPU 76 °C, GPU 70 °C.

Die Fühlerliste wird zur Laufzeit gesucht statt fest verdrahtet: welche es
gibt, hängt am Modell. Auf diesem Mac sind es 285 Temperaturfühler.

Zwei Leistungsprobleme, gefunden bevor sie jemandem auffallen konnten:

Die Suche geht alle 3486 Keys durch und braucht knapp eine Sekunde. Auf dem
Hauptthread wäre das eine spürbare Startverzögerung — sie läuft jetzt im
Hintergrund, bis dahin zeigt die Oberfläche "—" statt einer erfundenen Zahl.

Fünfzig Fühler zu lesen kostete 34 ms je Abtastung, bei 1 Hz also 3,4 % CPU.
Zwei Maßnahmen: Typ und Größe je Key werden zwischengespeichert (sie stehen in
der Firmware fest, sie bei jedem Lesen zu erfragen verdoppelte die
IOKit-Aufrufe), und Temperaturen werden höchstens alle zwei Sekunden neu
gelesen — sie bewegen sich in einer Sekunde ohnehin kaum. Ergebnis: 6 ms
Grundlast, 18 ms alle zwei Sekunden, im Mittel gut 1 %.

Dabei noch eine Eigenheit gefunden: die Byte-Reihenfolge im SMC ist nicht
durchgängig. Messwerte wie B0AV kommen little-endian aus dem Akku-Baustein,
die Metadaten des SMC selbst dagegen big-endian. #KEY little-endian gelesen
ergibt 2 651 652 096 statt 3486 — die Fühlersuche brach damit still ab und
alle Temperaturen blieben leer.

Lüfterdrehzahlen stehen jetzt im Sensor-Popover, mit Balken zwischen Minimum
und Maximum der Firmware: "2321 U/min" allein sagt niemandem, ob das viel ist.
Die Steuerung selbst kommt mit Phase 6 — Schreibzugriff auf den SMC verlangt
root — und der Popover sagt das auch.

145 Tests grün.
This commit is contained in:
Guido Schmit
2026-08-10 22:05:38 +02:00
parent 594d7c422a
commit a4cc75ab6e
10 changed files with 914 additions and 520 deletions

View File

@@ -1,6 +1,42 @@
{
"sourceLanguage": "en",
"strings": {
"%lld": {
"comment": "A label displaying the speed of a fan. The argument is the speed of the fan, in revolutions per minute.",
"isCommentAutoGenerated": true
},
"metric.battery": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Akku"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Battery"
}
}
}
},
"metric.battery.charging": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Lädt"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Charging"
}
}
}
},
"metric.cpu": {
"localizations": {
"de": {
@@ -17,6 +53,22 @@
}
}
},
"metric.cpu.perCore": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Je Kern"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Per core"
}
}
}
},
"metric.gpu": {
"localizations": {
"de": {
@@ -49,22 +101,6 @@
}
}
},
"metric.battery": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Akku"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Battery"
}
}
}
},
"metric.sensors": {
"localizations": {
"de": {
@@ -97,38 +133,102 @@
}
}
},
"metric.battery.charging": {
"metric.show": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Lädt"
"value": "Anzeigen"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Charging"
"value": "Show"
}
}
}
},
"metric.cpu.perCore": {
"metric.mode.usage": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Je Kern"
"value": "Auslastung"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Per core"
"value": "Usage"
}
}
}
},
"metric.mode.temperature": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Temperatur"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Temperature"
}
}
}
},
"metric.rpm": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "U/min"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "rpm"
}
}
}
},
"metric.fan.controlComing": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Die Lüftersteuerung kommt mit dem privilegierten Helfer — Schreibzugriff auf den SMC verlangt root."
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Fan control arrives with the privileged helper — writing to the SMC requires root."
}
}
}
},
"metric.fan %lld": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Lüfter %lld"
}
},
"en": {
"stringUnit": {
"state": "translated",
"value": "Fan %lld"
}
}
}
}
},
"version": "1.0"
"version": "1.1"
}