Systemleistung ist kein End-of-line-Test. Sie ist eine Entwurfsdisziplin: Hypothesen formulieren, realistische Last erzeugen, Signale korrelieren und Engpässe dort beseitigen, wo sie entstehen.
07MODULE
04TOOLS IM FOKUS
∞ITERATIONEN
FIELD GUIDE — 2026LESEZEIT 18 MIN
01 — FOUNDATIONS
Fundamentale & Metriken
Bevor ein Tool gestartet wird, muss klar sein, welche Systemfrage beantwortet werden soll. Diese Größen beschreiben Leistung aus unterschiedlichen Blickwinkeln.
τZEIT / ANFRAGE
Latenz
Latenz ist die verstrichene Zeit vom Absenden einer Anfrage (englisch: Request) bis zum Empfang ihrer Antwort. Auf dem Nutzerpfad umfasst sie Netzwerkübertragung und die Zeit in allen beteiligten Systemen. Ein niedriger Mittelwert kann eine langsame Minderheit verdecken.
FRAGE Wie lange wartet ein Nutzer?
λANFRAGEN / SEK.
Durchsatz
Durchsatz ist erfolgreich abgeschlossene Arbeit pro Zeit, zum Beispiel 120 Anfragen/s, 40 Transaktionen/min oder 8 MB/s. Immer mit Fehlerquote und Antwortzeit betrachten: mehr angebotene Last ist nicht mehr erledigte Arbeit.
FRAGE Wie viel Arbeit wird erledigt?
nGLEICHZEITIG
Gleichzeitigkeit (Concurrency)
Die Anzahl gleichzeitig aktiver Vorgänge. Sie ist nicht gleich Nutzerzahl oder Anfragerate: Ein Nutzer kann zwischen Aktionen pausieren, während ein asynchroner Vorgang noch nicht abgeschlossen und damit weiterhin „in flight“ ist.
FRAGE Wie viel Arbeit ist offen?
LWARTESCHLANGENMODELL
Little’s Law
Für ein stationäres System verbindet Little’s Law den mittleren Bestand L, den mittleren Durchsatz λ und die mittlere Verweildauer W eines Vorgangs innerhalb einer festgelegten Systemgrenze.
L = λ × W
FRAGE Wie viele Vorgänge sind im System?
Das Sättigungsbild lesen
Die angebotene Last ist die Arbeit, die Clients pro Sekunde anliefern; der Durchsatz ist die tatsächlich abgeschlossene Arbeit. Mit steigender Last wächst der Durchsatz zunächst annähernd linear. Erreicht eine Ressource ihre Kapazitätsgrenze, bilden sich Warteschlangen: Verweildauer und Zeitüberschreitungen (Timeouts) steigen, während der Durchsatz stagniert oder fällt. Beispiel: Steigt die Rate von 100 auf 150 Anfragen/s, der Durchsatz bleibt aber bei 120/s und die Warteschlange wächst, ist das System gesättigt. Dieser Knick ist aussagekräftiger als ein einzelner Maximalwert.
Service Level Indicator, Objective und Agreement
Ein Service Level Indicator (SLI, Dienstgütekennzahl) ist ein messbarer Wert für ein Nutzerergebnis, zum Beispiel der Anteil erfolgreicher Checkout-Anfragen mit weniger als 500 ms Antwortzeit. Ein Service Level Objective (SLO, Dienstgüteziel) legt den Zielwert und Zeitraum fest. Ein Service Level Agreement (SLA, Dienstgütevereinbarung) ist die externe Zusage samt möglichen Folgen bei Nichterfüllung. Das Error Budget (Fehlerbudget) ist der erlaubte Anteil an Nichterfüllung des SLO; bei 99,9 % Verfügbarkeit beträgt es 0,1 % des vereinbarten Zeitfensters. Das interne SLO wird üblicherweise strenger als das SLA gesetzt, damit vor einer Vertragsverletzung noch Reaktionszeit bleibt.
02 — LOAD TESTING
Lasttests, die etwas beweisen
Ein Lasttest ist ein reproduzierbares Experiment mit künstlich erzeugten Nutzeranfragen. Er beschreibt die Workload (Arbeitslast: Rate, Mischung und zeitlicher Verlauf der Anfragen), hält Testdaten unter Kontrolle und legt vor dem Lauf fest, woran Erfolg oder Abbruch gemessen wird.
KRITERIUM
k6
JMeter
Modell
JavaScript-Skripte, zuerst über die Command-Line Interface (CLI, Kommandozeile); Virtual Users (VUs, virtuelle Nutzer) oder Arrival-Rate-Executors (vorgegebene Anfragerate) modellieren die Arbeit.
Graphical User Interface (GUI, grafische Oberfläche) für Testpläne mit Thread Groups (parallelen Ausführungssträngen) und Samplern (einzelnen Aktionen); CLI für reproduzierbare Läufe in Continuous Integration (CI, automatisierten Build- und Testabläufen).
Stärken
Tests als Code, schnelle Starts, Prüfungen (Checks) und Grenzwerte (Thresholds) im Skript; gute CI-Integration.
Breite Protokoll- und Plugin-Auswahl, GUI für Exploration, etablierter Unternehmenseinsatz.
Beachten
Lastgenerator separat dimensionieren. Checks melden Ergebnisse, sind aber keine harten Abbruchkriterien: Dafür Thresholds setzen. VU-Kapazität prüfen.
Ergebnis-Listener bei hoher Last minimieren; GUI nicht als Generator einsetzen. Heap (Java-Arbeitsspeicher) und Lastgenerator überwachen.
Passend, wenn …
Versionierbare API-Tests und Pipeline-Gates im Vordergrund stehen.
Bestehende Testpläne, spezielle Protokolle oder visuelle Testflow-Modellierung wichtig sind.
02.1
k6: Anlaufphase, Checks und belastbare Grenzwerte
Ein Arrival-Rate-Modell gibt eine festgelegte Zahl neuer Anfragen pro Zeiteinheit vor, statt die Rate indirekt aus der Geschwindigkeit virtueller Nutzer abzuleiten. Die Ramp-up-Phase erhöht diese Rate schrittweise.
RUNk6 run -e BASE_URL=https://staging.example.com -e SKU=sku-42 -e TEST_TOKEN="$TEST_TOKEN" checkout-load.js
● ● ●BEISPIEL: k6-ZUSAMMENFASSUNGPASS
checks.........................: 99.8% ✓ 1198 ✗ 2
http_req_duration..............: avg=184ms p(95)=312ms
http_req_failed................: 0.17% 2 out of 1200
iterations.....................: 1200 20.0/s
vus_max........................: 34
Der Lauf erfüllt p(95)<400 und die Rate unter 1 %. Zwei fehlgeschlagene Prüfungen zeigen trotzdem einen fachlichen Fehler, den die reine Latenzgrenze nicht abbildet.
02.2
JMeter: wiederholbarer CLI-Lauf
Im Testplan: Thread Group, CSV Data Set (eindeutige Nutzer), HTTP Request Defaults, Header Manager, Assertions und Backend Listener. GUI zum Entwurf, Non-GUI für reproduzierbare Läufe.
Properties im Testplan mit ${__P(users,60)} auslesen. Daten pro VU eindeutig halten, Response-Assertions gezielt aktivieren und große Listener-Ergebnisse nicht im Injector-Speicher sammeln.
02.3
JMeter: Transaktionen und testdatengesteuerte Abläufe
Der Transaction Controller bündelt mehrere Sampler zu einer fachlichen Transaktion. Mit „Generate parent sample“ entsteht ein übergeordneter Messwert; ohne diese Option werden nur die Einzelschritte ausgewertet. CSV Data Set Config liefert pro Thread Testdaten und muss hinsichtlich Sharing, Dateiende und Wiederverwendung zur Thread Group passen.
JMX-Beispiel: Transaction Controller und CSV Data Set Config
Dieses gekürzte Beispiel liest Nutzerzeilen ein und führt Login, Warenkorb und Checkout als eine gemessene Transaktion aus. Bei nicht wiederverwendeten Daten müssen genügend eindeutige CSV-Zeilen für alle Threads vorhanden sein.
XML checkout-flow.jmx
<!-- Elemente liegen in der hashTree der ThreadGroup -->
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet"
testname="User data" enabled="true">
<stringProp name="filename">${__P(csv,users.csv)}</stringProp>
<stringProp name="variableNames">username,password,customer_id</stringProp>
<stringProp name="delimiter">,</stringProp>
<boolProp name="ignoreFirstLine">true</boolProp>
<boolProp name="quotedData">true</boolProp>
<boolProp name="recycle">false</boolProp>
<boolProp name="stopThread">true</boolProp>
<stringProp name="shareMode">shareMode.all</stringProp>
</CSVDataSet>
<hashTree/>
<TransactionController guiclass="TransactionControllerGui"
testclass="TransactionController" testname="Checkout transaction"
enabled="true">
<boolProp name="TransactionController.parent">true</boolProp>
</TransactionController>
<hashTree>
<HTTPSamplerProxy testname="Login"/>
<hashTree/>
<HTTPSamplerProxy testname="Add item to cart"/>
<hashTree/>
<HTTPSamplerProxy testname="Submit checkout"/>
<hashTree/>
</hashTree>
Auswertung: Der Parent-Sample-Wert umfasst die Transaktion inklusive Zwischenwartezeiten. Einzelsampler zusätzlich behalten, wenn einzelne Schritte diagnostiziert werden sollen. Testdaten anonymisieren; Passwörter nicht in CSV-Dateien committen.
JTL-Logs automatisiert mit Python auswerten
Der Parser erwartet JMeter-JTL als CSV mit Header und den Spalten label, elapsed und success. Er fasst Dauer, P95/P99 und Fehlerquote je Transaktion zusammen.
PY summarize_jtl.py
import csv
import math
import sys
from collections import defaultdict
def percentile(values, quantile):
ordered = sorted(values)
index = max(0, math.ceil(quantile * len(ordered)) - 1)
return ordered[index]
def summarize(path):
durations = defaultdict(list)
failures = defaultdict(int)
with open(path, newline="", encoding="utf-8") as source:
for row in csv.DictReader(source):
label = row["label"]
durations[label].append(int(row["elapsed"]))
failures[label] += row["success"].lower() != "true"
for label, samples in sorted(durations.items()):
error_rate = failures[label] / len(samples)
print(
f"{label}: n={len(samples)}, "
f"p95={percentile(samples, .95)}ms, "
f"p99={percentile(samples, .99)}ms, "
f"errors={error_rate:.2%}"
)
if __name__ == "__main__":
summarize(sys.argv[1] if len(sys.argv) > 1 else "results.jtl")
Die Sortierung im Speicher ist für moderate Testläufe geeignet; bei sehr großen Logs Streaming-Histogramme oder ein Metrics-Backend nutzen. JTL-Spalten hängen von der JMeter-Konfiguration ab. CI-Gates sollten Budgets über mehrere stabile Samples anwenden, nicht einen einzelnen Ausreißer.
03 — OBSERVABILITY
Signale zusammen lesen
Observability (Beobachtbarkeit) bedeutet, den inneren Zustand eines Systems aus seinen Ausgaben abzuleiten. Metriken sind über Zeit aggregierte Zahlen, Logs zeitgestempelte Ereignisse und Traces Ablaufspuren einer Anfrage über mehrere Services. Erst gemeinsam wird die Diagnose belastbar.
01METRIKENWas kippt wann? · RED / USE
→
02TRACESWo liegt die Zeit? · trace_id
→
03LOGSWas geschah genau? · span_id
Korrelieren, nicht nur sammeln
Verwende konsistente Attribute für Service, Umgebung und Version. Jeder Trace (Ablaufspur einer Anfrage) erhält eine Trace-ID (eindeutige Ablaufkennung); Logs übernehmen Trace-ID und Span-ID (Kennung eines einzelnen Arbeitsschritts) als strukturierte Felder. Metriken sollten Labels begrenzter Kardinalität (Anzahl möglicher Werte) nutzen, etwa ein Routenmuster statt einer vollständigen URL (Uniform Resource Locator, Webadresse). So führt ein Alarm vom Service-Dashboard zum Trace und zum passenden Log.
RED und USE als Startpunkt
RED steht für Rate (Anfragerate), Errors (Fehlerzahl) und Duration (Dauer) und prüft Services. USE steht für Utilization (Auslastung), Saturation (Rückstau) und Errors (Fehler) und prüft Ressourcen. Prüfe zusätzlich Warteschlangentiefe und Pool-Auslastung: Eine Central Processing Unit (CPU, Hauptprozessor) bei 40 % kann neben einem erschöpften Connection Pool (Verbindungspool) stehen, der Anfragen nacheinander statt parallel bearbeitet.
03.1
Grafana: Datenquellen, Panels und Zeitreihen
Grafana visualisiert und korreliert Messdaten; es ist typischerweise nicht selbst deren Quelle. Ein Dashboard fragt Data Sources wie Prometheus, Loki, Elasticsearch oder SQL-Datenbanken ab und rendert Resultate in Panels.
Vom Sample zum Panel
Eine Time Series (Zeitreihe) besteht aus Zeitstempeln und Werten, identifiziert durch Metrikname und Labels. Prometheus speichert Samples als numerische Messwerte: Counter steigen monoton und werden mit rate() oder increase() ausgewertet; Gauges wie Queue-Tiefe steigen und fallen. Histogramme bestehen aus Bucket-Zählern sowie _sum und _count. Ein Panel definiert Abfrage, Visualisierung, Einheit, Legende, Schwellenwerte und optionale Transformationen. Achsen und Einheiten müssen zur Messgröße passen.
Variables und Dashboard-Kontext
Variables parametrisieren Abfragen, zum Beispiel $environment, $service oder $instance. Grafana kann Optionen aus Label-Werten einer Data Source befüllen und als Dropdown oder Multi-Select anbieten. Mehrfachwerte müssen zur PromQL-Regex passen. Vermeide hochkardinale Labels wie Nutzer-ID, vollständige URL oder Request-ID. Halte Zeitbereich, Zeitzone und Refresh-Intervall konsistent; Deployment-Annotationen machen Vorher/Nachher-Vergleiche nachvollziehbar.
PromQL-Beispiele: P99-Latenz und CPU-Auslastung
Die P99-Abfrage setzt ein Prometheus-Histogramm http_request_duration_seconds_bucket voraus. Die erste CPU-Abfrage berechnet Prozess-CPU-Kerne aus einem Counter; die Node Exporter-Abfrage schätzt die Host-Auslastung.
Q PromQL
# P99 je Service im rollierenden 5-Minuten-Fenster
histogram_quantile(
0.99,
sum by (le, service) (
rate(http_request_duration_seconds_bucket{
environment=~"$environment", service=~"$service"
}[5m])
)
)
# Prozess-CPU-Kerne je Instanz (1.0 = ein voll genutzter Kern)
sum by (instance) (
rate(process_cpu_seconds_total{
job="$job", environment=~"$environment"
}[5m])
)
# Host-CPU-Auslastung in Prozent, aus idle-Zeit abgeleitet
100 * (1 - avg by (instance) (
rate(node_cpu_seconds_total{mode="idle", instance=~"$instance"}[5m])
))
Histogramm-Quantile sind abhängig von Bucket-Grenzen. Bei wenigen Samples schwankt P99 stark; Request-Anzahl, Fehler und mehrere Läufe gemeinsam betrachten. Metrik- und Labelnamen an die eigene Instrumentierung anpassen.
TAIL LATENCY
Der lange Schwanz gehört zum Produkt.
P95 ist die Grenze, unter der 95 % der Beobachtungen liegen; 5 % sind langsamer. P99 betrachtet das langsamste Prozent. Mittelwerte verschleiern genau diese Nutzererfahrung.
P50 82 msP95 410 msP99 1,2 s
LATENZ
1.2 s800 ms400 ms0
ANTEIL DER REQUESTS →
CPU-FREQUENZ
P-States & Throttling
CPU-P-States bezeichnen Performance-/Frequenzzustände. Moderne CPUs ändern Takt und Spannung dynamisch nach Last, Temperatur und Power-Budget. Niedriger Takt im Leerlauf ist normal; thermisches oder Power-Throttling kann unter Last Kapazität begrenzen. Takt, Temperatur, CPU-Zeit und Durchsatz gemeinsam vergleichen.
SYSTEMAUSLASTUNG
Load Average ist keine CPU-%
Linux Load Average zählt laufbereite Tasks und Tasks im ununterbrechbaren Sleep, meist I/O-Wait. Bei 8 Kernen bedeutet dauerhafter Load 8 etwa eine volle Run Queue; Load 16 weist auf Rückstau hin. vmstat, CPU-Steal, Run Queue und I/O-Latenz ergänzen, bevor du die Ursache festlegst.
04 — BOTTLENECK ANALYSIS
Vom Symptom zur Engstelle
Formuliere eine prüfbare Hypothese, ändere jeweils eine Variable und vergleiche denselben Workload. Korrelation lenkt die Suche; gezieltes Profiling bestätigt die Ursache.
A
Thread-Dumps lesen
Mehrere Dumps im Abstand von 5–10 Sekunden aufnehmen. BLOCKED deutet auf Monitor-Konkurrenz; viele WAITING können normal sein. Wiederkehrende Stackframes in RUNNABLE lokalisieren CPU-Arbeit. Deadlocks sind explizit markiert. Thread-Zustand mit CPU-Profil und Request-Trace abgleichen.
"http-worker-17" #84 RUNNABLE
at com.acme.Cart.calculate(Cart.java:142)
"pool-2-thread-1" #91 BLOCKED
- waiting to lock <0x00000007>
JVMB
Heap-Dumps & Speicherwachstum
Ein Dump ist eine Momentaufnahme, kein Zeitverlauf. In MAT/YourKit zuerst dominator tree und retained size prüfen, dann GC roots bis zur unerwarteten Referenz verfolgen. Wiederholte Dumps nach vergleichbarer Last zeigen, ob Objekte dauerhaft gehalten werden. Dumps können pausieren und sensible Daten enthalten.
Bei G1: -Xlog:gc*,safepoint:file=gc.log:time,uptime,level,tags. Pausendauer und -frequenz, Heap vor/nach GC, Humongous Allocation, Concurrent-Cycle-Dauer und Full GCs prüfen. Häufige lange Pausen weisen auf Allocation Pressure oder unpassende Heap-Größe hin; den Heap blind zu vergrößern kann Pausen verlängern. Allocation Rate und Live Set dazunehmen.
GC
04.1
Linux: von Übersicht zu Ursache
Erst den Engpass-Typ bestimmen, dann mit dem passenden Werkzeug enger heranzoomen.
● ● ●CPU / PROZESSE01
$ top -H -p 1842
%Cpu(s): 78.1 us, 8.2 sy, 9.4 id,
3.1 wa, 0.0 st
PID USER S %CPU
1943 app R 76.4
$ pidstat -u -t 1
Ein einzelner Thread bei 76 %: thread-spezifisch profilieren. Hohes wa: I/O prüfen. st bedeutet gestohlene VM-Zeit.
Hotspots nach kumulierter Zeit prüfen, Stacktraces aktivieren, Symbole verfügbar machen. Sampling ist statistisch; Rechte und Profiling-Overhead beachten.
BCC/bpftrace zeigen Kernel-Latenzen, Run-Queue-Wartezeit oder Block-I/O. Kernel-Version, BTF, Capabilities und Produktions-Overhead beachten.
Kommentierte Momentaufnahmen: top, vmstat und iostat
Beispielwerte sind illustrativ. Für eine Diagnose den Verlauf während derselben reproduzierbaren Testphase erfassen. Die erste vmstat-Zeile nach Programmstart enthält häufig Mittelwerte seit dem Systemstart.
● ● ●top: CPU UND PROZESSE
top - 14:32:10 up 12 days, 3 users
%Cpu(s): 71.0 us, 12.0 sy, 9.0 id,
7.0 wa, 1.0 st
MiB Mem : 16000 total, 1200 free
PID USER %CPU %MEM S COMMAND
1842 app 165 8.2 R java
us + sy ist hoch: User- und Kernel-Arbeit beanspruchen CPU. wa=7% weist zusätzlich auf I/O-Wartezeit hin. 165 % entspricht ungefähr 1,65 logischen CPUs; Thread-Ansicht und cgroup-Limits prüfen.
● ● ●vmstat: RUN QUEUE UND SWAP
vmstat 1
r b swpd free si so us sy id wa
9 2 524288 180000 128 256 71 12 9 7
11 3 524288 176000 64 128 74 13 6 7
r sind ausführbare oder laufende Tasks, b ununterbrechbar wartende Tasks. Anhaltendes si/so bedeutet Swap-Aktivität. Bei 8 vCPUs deutet r=9–11 auf CPU-Rückstau, beweist ihn ohne Verlauf und Kontext aber nicht.
nvme0n1 zeigt höhere mittlere Wartezeit und Queue als das zweite Gerät. Mapping, konkurrierende Workloads und Tail-Latenz prüfen. Bei parallelen SSDs ist %util allein keine sichere Kapazitätsgrenze.
DATENBANKEN
Query-Plan statt Bauchgefühl
POSTGRESQL
Slow Queries nach Gesamtzeit, Aufrufzahl und mittlerer Laufzeit sortieren. pg_stat_statements aggregiert Query-Fingerprints. Mit repräsentativen Parametern EXPLAIN (ANALYZE, BUFFERS) ausführen und geschätzte gegen tatsächliche Zeilen vergleichen.
Seq Scan ist nicht automatisch falsch. Verdächtig sind große Schätzabweichungen, viele gelesene Blöcke, Sorts auf Disk oder Nested Loops mit sehr vielen Wiederholungen.
BEISPIEL: FILTER + SORT
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, created_at FROM orders
WHERE customer_id = 42
ORDER BY created_at DESC LIMIT 20;
CREATE INDEX CONCURRENTLY
idx_orders_customer_created
ON orders (customer_id, created_at DESC);
● ● ●BEISPIEL: POSTGRESQL-PLANVORHER → NACHHER
-- ohne passenden Index
Seq Scan on orders (actual rows=18432)
Rows Removed by Filter: 181568
Execution Time: 18.432 ms
-- mit (customer_id, created_at DESC)
Index Scan using idx_orders_customer_created
on orders (actual rows=20)
Execution Time: 0.084 ms
Illustrative Werte derselben Beispielabfrage: 18,432 ms auf 0,084 ms. Vergleiche denselben Datensatz und dieselben Parameter; ein schnellerer Einzelplan beweist nicht automatisch bessere Gesamtleistung.
EXPLAIN visuell lesen: Scan, Sortierung und tatsächliche Zeilen
Der erste Plan filtert 200.000 Tabellenzeilen und sortiert die Treffer. Der optimierte Index beginnt mit der Gleichheitsbedingung customer_id, hält danach created_at absteigend sortiert und kann nach 20 Treffern stoppen.
Viele Zeilen geprüft und anschließend sortiert. Bei selektivem Filter entsteht vermeidbare Arbeit.
NACHHER · geordneter Indexzugriff
Limit (actual rows=20 loops=1)
-> Index Scan using idx_orders_customer_created
on orders (actual rows=20 loops=1)
Index Cond: (customer_id = 42)
Buffers: shared hit=24 read=2
Execution Time: 0.084 ms
Filter und Sortierreihenfolge passen zum Index; das LIMIT beendet den Scan früh.
Zeiten hängen von Cache, Datenverteilung, Hardware und Parallelität ab. EXPLAIN ANALYZE führt die Abfrage tatsächlich aus. Vergleiche erwartete und tatsächliche Zeilen sowie Buffer, nicht nur Gesamtdauer.
05 — DISTRIBUTED SYSTEMS
Engpässe über Systemgrenzen
Verteilte Systeme vervielfachen neben dem Durchsatz auch Netzwerkhops, Queues, Timeouts und Fehlerpfade. Jede Grenze braucht ein Budget und beobachtbares Verhalten unter Sättigung.
EDGEClientDNS · CDN
INGRESSGatewayAuth · Limits
COMPUTEServicePool · Queue
STATECache / DBHit Rate · I/O
SCHICHT
TYPISCHES SYMPTOM
ERSTE PRÜFUNG
GEGENMASSNAHME
API Gateway
Queueing vor Services, 429/5xx, TLS-CPU, Limits erreicht
Kapazität/Parallelität erhöhen, Poison Messages isolieren, Backpressure und maximale Queue-Länge.
Kubernetes
CPU throttling, Neustarts oder träges Autoscaling
Throttled time, Requests/Limits, HPA-Metrik, Readiness, Scale-up-Verzögerung
Limits anhand Messungen setzen, HPA passend dimensionieren; Cold Start und Warm-up in Kapazität einrechnen.
06 — FIELD GUIDE
Ein belastbarer Arbeitsablauf
Die beste Analyse endet nicht mit einem Dashboard. Sie führt zu einer Entscheidung, einem kontrollierten Eingriff und einem wiederholbaren Nachweis.
01
Ziel und Grenzen festlegen
Nutzerpfad, SLI/SLO, Lastprofil, Testfenster, Abbruchkriterien und Verantwortliche dokumentieren.
02
Workload modellieren
Transaktionsmix, Think Time, Datenverteilung, Cache-Warm-up und Spitzenlast aus Produktionsdaten ableiten und anonymisieren.
03
Baseline und Generator prüfen
Testdaten zurücksetzen, Generator beobachten, Rate verifizieren sowie Metriken, Traces und Logs zeitlich synchronisieren.
04
Eine Dimension verändern
Baseline, Ziel-Last, Stress- und Soak-Test unterscheiden. Build, Konfiguration, Daten und Skript pro Lauf versionieren.
05
Ursache triangulieren
Mit RED/USE eingrenzen, Trace öffnen, Ressource oder Thread profilieren und gegen die konkrete Hypothese wiederholen.
06
Kapazität kommunizieren
Durchsatz am SLO, P95/P99, Fehlerquote, Sättigungsgrenze und Sicherheitsmarge berichten, nicht nur den Bestwert.
↗
DER LERNPFAD IN KURZFORM
Fundamentale → Tool → Signale → System → Architektur
Baue entlang echter Fragen: Checkout mit k6 belasten, ein P95-Dashboard erstellen, einen langsamen SQL-Plan erklären und ein CPU-Profil vor/nach einer Änderung vergleichen. Jedes Projekt hält Hypothese, Methode, Ergebnis und Trade-off fest.
07 — DELIVERY GATES
Performance-Tests in CI/CD
Performance-Prüfungen werden dann verlässlich, wenn sie zur passenden Pipeline-Stufe passen: schnell und deterministisch bei jeder Änderung, umfassender auf planbaren Testumgebungen und langlaufend als regelmäßiger Kapazitätsnachweis.
Teststufen nach Feedbackzeit
Pull Request: kurze Smoke- oder Mikrobenchmarks mit kleiner, stabiler Last und klaren Korrektheitschecks. Merge oder Release-Kandidat: repräsentativer Workload gegen feste Umgebung und Baseline. Nightly: Ramp-up, Stress- und Soak-Tests sowie größere Datenmengen. Große Lasttests nicht auf gemeinsam genutzten Runnern ausführen, wenn deren CPU, Netzwerk oder Nachbarn nicht kontrolliert sind.
Performance Budget definieren
Budgetiert werden Nutzer-SLIs und nicht bloß Ressourcen: etwa Fehlerquote unter 0,5 %, P95 unter 350 ms, P99 unter 900 ms bei mindestens 100 Requests/s. Zusätzlich Generator-Drops auf null und Mindestzahl erfolgreicher Samples fordern. Absolute Grenzwerte schützen das Ziel; relative Regression gegen eine versionierte Baseline erkennt Änderungen. Vergleichswerte nur bei gleicher Hardware, Datenmenge, Konfiguration und Testdauer gegenüberstellen.
Kapazitätsziele, Stabilität, Fehlerbudget und Generator-Gesundheit
Trendbericht und Ticket/Alarm bei bestätigter Regression
Beispiel: GitHub-Actions-Quality-Gate
Das Beispiel startet einen kurzen k6-Lauf, macht Schwellenwerte zum Prozess-Exitcode und archiviert JSON-Ergebnisse. Secrets kommen aus dem CI-Secret-Store. Für belastbare Vergleiche Runner-Größe und Zielumgebung fixieren; das PR-Beispiel ist ein Regression-Signal, keine abschließende Kapazitätsmessung.
In k6 Thresholds zum Beispiel http_req_failed: ['rate<0.005'], http_req_duration: ['p(95)<350', 'p(99)<900'] und dropped_iterations: ['count==0'] definieren. Ein fehlgeschlagener Threshold liefert einen von null verschiedenen Exitcode.