%CPU-Auslastung ist eine Lüge
(brendanlong.com)- Die Leistungsgrenze eines Servers wird üblicherweise anhand der % CPU-Auslastung aus Monitoring-Tools wie
topbeurteilt, tatsächlich bildet dieser Wert die Leistung jedoch nicht linear ab - Tests mit stress-ng in einer Ryzen-9-5900X-Umgebung zeigen, dass bei 50 % Auslastung die tatsächliche Arbeitslast bereits 60–100 % erreichen kann – mit einer erheblichen Abweichung zwischen Kennzahl und Realität
- Hauptursachen sind Hyper-Threading und Turbo Boost: gemeinsame Ressourcennutzung zwischen logischen Kernen und veränderliche Taktraten verzerren die Kennzahl
- Daher ist statt einer simplen CPU-Auslastung der Vergleich zwischen benchmarkbasierter tatsächlich verarbeitbarer Arbeitsmenge und aktuellem Durchsatz der genauere Indikator
- Wer CPU-Auslastung linear interpretiert, riskiert große Fehler bei der Leistungsschätzung; für die Systemplanung ist deshalb ein benchmarkbasierter Ansatz nötig
Diskrepanz zwischen CPU-Auslastungswerten eines Servers und dem tatsächlichen Durchsatz
- Im Serverbetrieb möchten viele wissen, ob ein System nahe an seiner Maximalauslastung läuft
- Meist wird dafür in Monitoring-Tools wie
topauf den höchsten Wert unter Netzwerk-, Speicher- und CPU-Auslastung geschaut - In der Praxis tritt jedoch das Problem auf, dass CPU-Auslastungswerte und die tatsächlich verarbeitbare Arbeitsmenge nicht linear ansteigen
Testumgebung und Methode
- Experiment auf Basis eines Ubuntu-Desktops mit Ryzen 9 5900X (12 Kerne/24 Threads)
- Precision Boost Overdrive (Turbo) aktiviert
- Mit stress-ng wurden verschiedene Lasten simuliert (1–24 Worker, 1–100 % Auslastung)
- Gemessene Kennzahlen: vom System gemeldete CPU-Auslastung und tatsächliche Rechenmenge (Bogo ops)
Zusammenfassung der Ergebnisse
- Allgemeine CPU-Last: bei 50 % Auslastung tatsächlich 60–65 % Durchsatz
- 64-Bit-Integer-Berechnungen: bei 50 % Auslastung 65–85 % Durchsatz
- Matrixberechnungen (Matrix math): bei 50 % Auslastung 80–100 % Durchsatz
- Tatsächlich steigt die CPU-Auslastung selbst dann weiter, wenn zusätzliche Worker nichts mehr zur Leistung beitragen
Ursachenanalyse
-
Hyper-Threading
- Struktur aus 12 physischen Kernen + 12 logischen Kernen
- Bis zu 12 Worker werden optimal auf physische Kerne verteilt, bei mehr als 12 sinkt die Leistung durch gemeinsame Nutzung logischer Kerne
- Besonders bei SIMD-Berechnungen (Matrixberechnungen) ist keine Leistungssteigerung möglich, weil die Ressourcen geteilt werden
-
Turbo Boost
- Bei geringer Last 4,9 GHz → bei Volllast 4,3 GHz, also 15 % weniger Takt
- Dadurch entsteht eine Verzerrung in der Formel zur CPU-Auslastung (= busy cycles / total cycles)
- Da der Nenner (Gesamtzahl der Zyklen) sinkt, wird der Anstieg der Auslastung gegenüber der tatsächlichen Arbeitsmenge überbewertet
Implikationen
- CPU-Auslastung ist kein absoluter Leistungsindikator
- Bei Server-Kapazitätsplanung und Leistungsprognosen sollte man:
- 1. mit Benchmarks den maximalen Durchsatz messen
- 2. den Echtzeit-Durchsatz überwachen
- 3. durch Vergleich beider Werte beurteilen, ob man sich der Leistungsgrenze nähert
- Je nach CPU-Architektur (AMD vs Intel), Hyper-Threading-Effizienz und Turbo-Verhalten sind die Abweichungen groß; daher ist eine Analyse pro Prozessor nötig
Fazit
- CPU-Auslastung ist lediglich das Verhältnis beschäftigter Zyklen und bildet die tatsächliche Verarbeitungsleistung nicht präzise ab
- Selbst bei effizienter Nutzung können „50 % Auslastung“ bereits 80–100 % der Maximalleistung bedeuten
- Daher sollten sich Leistungsmonitoring und Systemplanung nicht auf CPU-Auslastung, sondern auf benchmarkbasierten Arbeitsdurchsatz stützen
3 Kommentare
In realen HPC-Umgebungen werden Cluster grundsätzlich mit deaktiviertem Hyper-Threading konfiguriert.
Hacker-News-Kommentare
Ich halte CPU utilization nicht für eine Lüge, insofern als dabei eine klar definierte Größe gemessen wird. Aber wenn Menschen versuchen, daraus ein Kapazitätsmodell zu extrapolieren, erleben sie oft eine Diskrepanz zwischen Erwartung und Realität
Hyperthreading (SMT) und Turbo (Clock-Scaling) sind nur einige von vielen Variablen, die Nichtlinearität verursachen; auch zwischen Kernen geteilte Speicherbandbreite, Interconnect-Kapazität und Prozessor-Cache sind Ressourcen, die mit steigender Last „erschöpft“ werden
Auch auf Software-Ebene können Phänomene wie etwa Spinlocks nichtlineare Auswirkungen auf die utilization haben
Die meisten CPU-utilization-Metriken bilden lange Mittelwerte über mehrere Sekunden bis hin zu einer Minute, während die für latenzsensitive Server entscheidenden Dinge innerhalb von Dutzenden bis Hunderten Millisekunden passieren
Deshalb kann eine über mehrere Sekunden gemittelte utilization Burst-Muster nicht von gleichmäßigen Mustern unterscheiden
Aber auch der vorgeschlagene Ansatz, also zu „benchmarken, wie viel Arbeit ein Server leisten kann, bevor Fehler oder unzulässige Latenz auftreten“, ist im Kern instabil
Wenn man versucht, den Punkt zu finden, an dem ein Server instabil wird, werden die Messwerte sehr noisy, und auch aus Sicht der Queueing-Theorie wird in der Nähe des Kipppunkts jedes Rauschen verstärkt
Außerdem ist schon die Definition von „wie viel Arbeit der Server gerade macht“ oft instabil (RPS? Die Kosten pro Request sind unterschiedlich, und auch IPC variiert je nach Zeitpunkt)
Am Ende sind die Konfidenzintervalle aus einem Lasttest-Ansatz ungefähr auf demselben Niveau wie empirische Modelle auf Basis von utilization-Metriken. Voraussetzung ist, dass utilization korrekt gemessen wird
Wenn man mit perf oder ftrace umgehen kann, bekommt man kurzfristig sehr detaillierte Prozessor-Metriken und kann direkt verschiedene Ursachen sehen, etwa CPU-Stalls durch Cache-Misses oder Memory Access, Scheduler-Effekte usw.
Die meisten wissen aber selbst dann nicht, was sie mit Metriken wie IPC oder Cache-Hit-Rate anfangen sollen
Am Ende interessieren sich die meisten eigentlich für Latenz und utilization
Grob gesagt gibt es bei den meisten Workloads kaum Latenzprobleme, solange die CPU utilization nicht über 80 % steigt
Oberhalb davon beginnt sie die Workload-Latenz aber ernsthaft zu beeinflussen
Wie stark die Latenz beeinflusst wird, lässt sich nur durch Messen des eigenen Workloads herausfinden
Wie latenzsensitiv man ist, hängt auch von Organisation und Zielen ab, und manchmal ist die Optimierung des Throughput wichtiger
Wenn man sowohl auf Latenz als auch auf Throughput achten muss, sollte man beides messen und den passenden Trade-off selbst festlegen
Ich denke, einer der Kernpunkte ist gerade, dass schon die Definition von „Arbeitsmenge“ schwankt
Es macht zum Beispiel einen Unterschied, ob es um echte Nutzeranfragen in einem öffentlich erreichbaren Dienst geht oder um einen KI-Trainings-Workload, der im Backend gelagerte Daten in Ruhe berechnet
Mein Ansatz ist, dass man in modernen Multicore-/Hyperthreaded-CPU-Umgebungen, in denen Bursts zwangsläufig gelegentlich auftreten, einen Server bei 60 % CPU utilization bereits als „hoch ausgelastet“ betrachten sollte
Wenn er über einen erheblichen Teil des Tages bei mehr als 60 % liegt, halte ich es für angemessen, die Arbeit aufzuteilen (vor allem bei Diensten, die auf Nutzeranfragen reagieren)
Früher führte so ein Maßstab oft dazu, dass man über Cloud-Autoscaling nachdachte
Heute kann man Server mit über 100 Kernen für rund 30.000 Dollar einsetzen, was die Lage komplizierter macht
Heute würde ich eher zu einem Hybrid-Ansatz tendieren: reale Server-Hardware etwas zu großzügig provisionieren und je nach Bedarf auf Cloud-Services (oder eine interne Cloud auf Kubernetes-Basis) erweitern
StackOverflow hat in seinen Anfangsjahren enormen Traffic mit dedizierten Racks und 10-Gbps-Uplink sehr effizient betrieben, und heute ist so etwas noch leichter umsetzbar
Mein Maßstab ist letztlich: Wenn die CPU load länger als 30 Minuten bei 65 % bleibt, gilt das für mich bereits als 100 % effektive Nutzung, und ich würde davon ausgehen, dass bald skaliert werden muss
In der Keynote der jüngsten IEEE Hot Interconnects wurde auch ein Beispiel für Latenz-Tuning bei Ultra Ethernet erwähnt
Auf einer Skala von 2 oder 5 Sekunden sieht alles flach aus, aber wenn man auf 100-ms-Skala schaut, werden Frame-Bursts klar sichtbar
Wenn also das Messfenster des Profilings nicht zum realen Workload passt, kann man durch False Negatives zu falschen Entscheidungen kommen, was das Problem noch verschärft
Dem Gesagten stimme ich vollkommen zu
Gerade wegen der nichtlinearen Natur von CPU utilization entfernt sich der Prozentwert selbst von der Realität
Anders gesagt: Die Behauptung ist, dass nur CPU utilization, gemessen in %, eine Lüge ist
Wenn zwei Workloads beide 100 % CPU-Auslastung anzeigen, aber einer deutlich mehr Strom verbraucht und die CPU-Temperatur stark anhebt, drängt sich die Frage auf, ob dieser Workload nicht tatsächlich mehr Transistor-Ressourcen nutzt
Auch wenn CPU utilization kein perfekter Messwert ist, ließ er sich in der Praxis dennoch nützlich einsetzen
Schon aus einfacher SRE-Erfahrung heraus haben wir bei CPU-bound Tasks die Queueing-Theorie mit CPU-utilization-Werten kombiniert, um vor großen Events die Servergröße zu bestimmen, und selbst mit einem deutlich konservativeren %CPU-Kriterium als bei „traditionelleren“ Ansätzen war das Ergebnis wesentlich kosteneffizienter
Der Kernpunkt ist: Auch einen leicht ungenauen Messwert kann man nutzen, wenn er vor Ort praktisch brauchbar ist, statt sich darüber übermäßig Sorgen zu machen
Allerdings haben wir die CPU utilization in Production bewusst immer unter 40 % gehalten, um in verschiedensten Situationen etwas Headroom zu haben
Schade ist, dass dem Autor eine saubere logische Begründung dafür fehlt, warum man hohe utilization aus Sicht der Queueing-Theorie vermeiden sollte
Ich denke auch, dass selbst etwas schlampige Metriken völlig ausreichen können, wenn sie in der Praxis sinnvoll eingesetzt werden
Zum Beispiel habe ich erlebt, dass es operativ kaum einen Unterschied macht, ob man einfach den Durchschnitt oder Maximalwert von Percentile-Metriken je Host nimmt oder Percentiles erst bei der Endaggregation hostweiser Histogramme berechnet
Manche legen sehr viel Wert darauf, ob etwas mathematisch streng richtig oder falsch ist, aber für den realen Betrieb hat das oft kaum Auswirkungen
40 % ist eigentlich schon eine ziemlich lockere, also komfortable Auslastung
Wenn man CPU% und loadavg zusammen betrachtet, kann man den Systemzustand ziemlich gut erfassen
Wenn loadavg hoch ist, CPU% aber niedrig, kann das bedeuten, dass man an Netzwerk oder I/O hängt oder etwa auf System Calls wartet
Wenn man in so einem Fall nur auf CPU% schaut, übersieht man leicht, wo das System tatsächlich leidet
Ich habe das Gefühl, dieselbe Geschichte schon einmal gehört zu haben
Das, was der Autor anspricht, wird in Büchern über Queueing-Theorie seit Jahrzehnten wiederholt, und trotzdem wirkt es, als hätte er es gerade erst entdeckt
Ich musste an Brendan Greggs Artikel "CPU Utilization is Wrong" denken
Der Kern dieses Blogposts ist, dass CPU utilization nur den „Zustand“ betrachtet, ob die CPU beschäftigt ist, und dabei sogar Leerlauf der CPU als busy einordnet
IPC ist dann die Metrik, mit der man die tatsächlich geleistete effektive Arbeit innerhalb dieses busy-Zustands erfassen kann
Falls es noch einen anderen Brendan gibt, hoffe ich, dass jemand das erklären kann
Ich denke, man sollte die durch Hyperthreading bereitgestellte Leistung nicht als Verdopplung rechnen
In der Praxis brachte selbst gut genutztes Hyperthreading oft nur etwa 15 bis 30 % zusätzliche Leistung. Die Latenz kann dafür aber doppelt so hoch werden
Man muss auch Taktabsenkungen bei hoher Core-Auslastung berücksichtigen, deshalb sollte man in der Praxis immer vorsichtig mit Nichtlinearitäten sein
Schon mit den Informationen des Betriebssystems könnte man die Effekte von Hyperthreading und Taktabsenkung einrechnen und dadurch eine deutlich genauere utilization-Schätzung erhalten
Darüber hinaus auch noch Cache-/Speicherbandbreiten-Limits oder Pipeline-Stalls als Ursache für Performance-Einbrüche zu modellieren, halte ich ebenfalls nicht für besonders schwierig
Ein zusätzlicher Faktor, der es kompliziert macht: Die Effizienz von Hyperthreading variiert extrem je nach CPU-Architektur und Workload
So liefert etwa AMD (besonders aktuelles Zen) tendenziell deutlich unabhängigere Performance als Intel, vorausgesetzt, es gibt keinen Memory-Bandwidth-Flaschenhals
Bei speichergebundenen Anwendungen sieht man durch Hyperthreading oft besseres Scaling
Ein Renderer-Projekt, für das ich früher zuständig war, war memory-bound, und allein durch Hyperthreading haben wir dort 60 bis 70 % Leistungszuwachs gesehen
Ich habe früher einmal auf einem i7-3770K (4C/8T) mit POV-Ray einen kleinen Benchmark gefahren
Von 1 Thread auf 2 Threads war es exakt doppelt so schnell, von 2 auf 4 ebenfalls, aber von 4 auf 8 gab es nur noch 15 % Zuwachs
Mit einem ungewöhnlichen Benchmark, der absichtlich immer wieder Cache-Misses provoziert, könnte man aus SMT vielleicht fast die doppelte Leistung herausholen, aber wie realistisch das ist, ist fraglich
Nachtrag: Ich überlege, den POV-Ray-Test noch einmal laufen zu lassen. Ist wirklich lange her, da kommt Nostalgie auf
Es wirkt, als hätte der Autor erkannt, dass Leistung nicht linear mit dem %CPU-utilization-Wert skaliert, und daraus dann geschlossen, dass %CPU utilization selbst eine „Lüge“ sei
Selbst ohne Hyperthreading oder Clock-Throttling erhält man kein exakt proportionales Scaling, auch nicht bei vermeintlich variablenarmen Fällen wie Apple Silicon
Sobald mehrere Kerne gleichzeitig genutzt werden, treten häufig Bottlenecks bei anderen Ressourcen als der CPU auf, etwa Datenübertragungs-Overhead, was ähnliche Situationen regelmäßig erzeugt
Der Autor verwendet den Begriff core auf verwirrende und nicht standardkonforme Weise
Er bezeichnet einen 5900X als 24-Core-System, obwohl es tatsächlich 12 physische Kerne mit 24 Hyperthreads sind
Zwölf davon sind physische Kerne, und die übrigen zwölf sind Threads, die jeweils an diese Kerne gebunden sind
Selbst wenn es zwei Instruction Pipelines gibt, werden die internen Functional Units gemeinsam genutzt
Eine Analogie, die mir von früher im Gedächtnis geblieben ist, als ich das einmal meinem kleinen Bruder erklären wollte, der Hyperthreading nicht gut kannte: Es ist wie zweilagiges Toilettenpapier
Man kann daraus nicht 24 voneinander getrennte Rollen machen, aber es ist ungefähr so, als würde man eine 12er-Packung doppelt so nützlich verwenden
Nach dem Feedback habe ich die Beschreibung auf 12 Cores / 24 Threads korrigiert
Mein Betriebssystem hat die utilization allerdings als 24 Cores angezeigt, was zusätzlich verwirrend war
Es wäre interessant, wenn Intel softwaredefinierte Cores herausbringen würde
Das wäre gewissermaßen das logische Gegenstück zu Hyperthreading: zwei oder mehr Cores teilen sich Ressourcen und werden zu „einem großen Core“ zusammengeführt
Siehe den folgenden Patentlink
https://patents.google.com/patent/EP4579444A1/en
Wenn ein SMT-Paar denselben Typ Workload ausführt, sinkt der SMT-Effekt wegen Konkurrenz um interne Ressourcen und Execution Units
Sind die Workloads hingegen völlig unterschiedlich, kann der Boost sogar größer ausfallen
Bei modernen CPUs wird alles noch komplizierter, weil jetzt auch P-Cores, E-Cores, Turbo/Nicht-Turbo usw. dazukommen
Es gab eine Studie, wonach das Hinzufügen von SMT pro Watt mehr Leistungsgewinn bringt als das Hinzufügen von Turbo, was ich sehr interessant fand
Das spricht mir wirklich aus der Seele
Vor Jahren musste ich einmal meinem Manager erklären, dass die Server-CPU bereits bei 60 % war und praktisch keine Reserven mehr hatte, und er sah mich nur mit einem seltsamen Blick an
Damals hätte ich genau so eine Erklärung gebraucht
Wenn man dazu noch Queueing-Theorie erklärt, ist die Wirkung perfekt
Unter 60 % ist Queueing-Delay praktisch vernachlässigbar
Ab über 70 % wird die Verzögerung deutlich spürbar, und ab 80 % verdoppelt sie sich fast
In meiner praktischen Erfahrung habe ich 65 % anhand der P95-Zeit als Zielwert gesetzt, und das entsprach fast genau dem theoretischen Maßstab
Die praktische Regel lautet also: „60 % ist die Nutzungsgrenze, ab 80 % explodiert die Latenz“
Das kann aber je nach Workload völlig anders aussehen
Besonders heute, wo Server-CPUs 32 Kerne und mehr haben, gilt das erst recht
CPU utilization verhält sich oft nicht so, wie man es erwarten würde
Bei solchen Artikeln hätte ich ursprünglich eher eine Diskussion darüber erwartet, wie utilization unter Linux oder Windows berechnet wird; tatsächlich gibt es aber viele Fälle, in denen die CPU wegen RAM-Bottlenecks untätig wartet oder heruntertaktet
CPU utilization misst tatsächlich nur, wie viele Threads das OS (ob Windows oder Linux) den einzelnen Kernen zuweist
Selbst wenn dieser Thread zu 100 % in memcpy wartet, wird das als utilization gezählt
Der Vorteil von Hyperthreading ist, dass, wenn ein Thread an AVX-/Vektoreinheiten hängt und ein anderer eher an einfachem memcpy/RAM, die Auslastung der jeweiligen Einheiten steigen kann, was insgesamt Performance und utilization erhöht
Letztlich ist CPU utilization seit Langem ein Thema, das sich intuitiv nur schwer greifen lässt, und es tauchen immer wieder neue Perspektiven darauf auf
Trotzdem bleibt es immer ein interessantes Thema
Die eigentliche „Lüge“ ist der Glaube, dass Hyperthreaded-Cores genauso funktionieren wie echte Cores
Dadurch, dass wir das nun seit über 20 Jahren ständig verwenden, vergisst man leicht das ursprüngliche Wesen und stellt dann immer wieder überrascht fest, warum Performance-Messwerte seltsam aussehen
Noch etwas: Ein Prozessor ist im Grunde entweder „in Ausführung“ (100 %) oder „wartend“ (0 %)
Dass man dazwischen einen Prozentwert vergibt, bedeutet letztlich nur, dass man einen Mittelwert über ein bestimmtes Zeitfenster bildet
Ich hatte einmal ein ähnliches Gespräch
Manager: Die CPU utilization liegt bei 100 %, sollten wir den Server nicht auf eine größere Instanz umstellen?
Ich: „Aber macht die CPU gerade überhaupt nützliche Arbeit?“
Am Ende wurde auch Busy Waiting als CPU utilization gezählt, sodass nur die Zahl stieg, unabhängig von tatsächlich effektiver Arbeit
Das ist die richtige Formulierung.