# 4.10 Ressourcenengpässe erkennen

Ein Dienst kann korrekt konfiguriert sein und trotzdem langsam, instabil oder nicht erreichbar werden, wenn ihm oder dem Gesamtsystem benötigte Ressourcen fehlen.

> **Grundsatz:**  
> Ein einzelner hoher Messwert beweist noch keinen Engpass. Entscheidend sind Messdauer, Vergleichswerte, Auslastungsursache und der zeitliche Zusammenhang mit der Störung.

---

**Ziele dieser Seite**

Nach dieser Seite sollst du:

- CPU-, Arbeitsspeicher- und I/O-Engpässe erkennen können,
- Lastspitzen von dauerhaftem Ressourcenmangel unterscheiden können,
- System- und Prozesswerte getrennt untersuchen können,
- physischen, virtuellen und residenten Speicher unterscheiden können,
- Paging und Swapping richtig bewerten können,
- Datenträgerlatenz und Warteschlangen berücksichtigen können,
- Handle-, Thread-, Prozess- und Dateideskriptorgrenzen prüfen können,
- Ressourcenwerte über mehrere Messpunkte beobachten können,
- Betriebssystemprotokolle nach Ressourcenfehlern durchsuchen können,
- Ergebnisse mit dem Zeitpunkt einer Dienststörung verbinden können.

---

<details>
<summary><strong>1. Welche Ressourcen können einen Dienst begrenzen?</strong></summary>

| Ressource | Typisches Fehlerbild |
|---|---|
| CPU | Hohe Antwortzeiten, Zeitüberschreitungen, verzögerte Verarbeitung |
| Arbeitsspeicher | Paging, Prozessabbrüche, fehlgeschlagene Allokationen |
| Swap beziehungsweise Auslagerungsdatei | Hohe Latenz durch Speicherauslagerung |
| Datenträger-I/O | Lange Wartezeiten, blockierte Prozesse, langsame Datenbank |
| Speicherplatz | Schreiben, Starten oder Protokollieren schlägt fehl |
| Inodes | Linux kann trotz freiem Speicherplatz keine Dateien anlegen |
| Dateideskriptoren | Neue Dateien oder Sockets können nicht geöffnet werden |
| Windows-Handles | Zugriff auf Dateien, Registry, Events oder Prozesse schlägt fehl |
| Threads | Neue Aufgaben oder Verbindungen können nicht verarbeitet werden |
| Prozesslimit | Neue Prozesse können nicht erzeugt werden |
| Netzwerkbandbreite | Langsame Übertragung und Warteschlangen |
| Verbindungspool | Neue Datenbank- oder HTTP-Verbindungen warten |
| Portbereich | Neue ausgehende TCP-Verbindungen schlagen fehl |
| GPU oder Beschleuniger | Spezialisierte Berechnung kann nicht ausgeführt werden |
| Quota | Benutzer oder Dienst darf keine weiteren Daten speichern |
| Containerlimit | Dienst erreicht CPU-, RAM- oder Prozessgrenze des Containers |

</details>

---

<details>
<summary><strong>2. Auslastung und Engpass unterscheiden</strong></summary>

| Zustand | Beschreibung |
|---|---|
| Auslastung | Eine Ressource wird verwendet |
| Hohe Auslastung | Ressource wird stark verwendet, Dienst funktioniert aber noch |
| Sättigung | Neue Arbeit muss warten |
| Engpass | Ressourcenbegrenzung beeinträchtigt die benötigte Funktion |
| Überlast | Eingehende Arbeit übersteigt dauerhaft die Verarbeitungskapazität |
| Ressourcenleck | Verbrauch steigt, obwohl abgeschlossene Arbeit Ressourcen freigeben sollte |
| Grenzwertfehler | Konfiguriertes Limit wird vor der technischen Kapazität erreicht |

**Beispiel:**

```text
CPU-Auslastung: 95 %
Antwortzeit:     normal
Warteschlange:   niedrig
Fehler:          keine
```

Das ist hohe Auslastung, aber noch kein bewiesener Engpass.

```text
CPU-Auslastung: 95 %
Antwortzeit:     stark erhöht
Warteschlange:   wächst
Timeouts:        vorhanden
```

Hier besteht ein belastbarer Hinweis auf CPU-Sättigung.

</details>

---

<details>
<summary><strong>3. Immer über mehrere Messpunkte prüfen</strong></summary>

Eine Momentaufnahme kann zufällig während einer kurzen Lastspitze entstehen.

**Empfohlene Messstruktur:**

```text
Zeitpunkt
CPU gesamt
CPU des Dienstprozesses
verfügbarer Arbeitsspeicher
Swap- beziehungsweise Paging-Aktivität
Datenträger-I/O und Wartezeit
Anzahl aktiver Anfragen
Anwendungsantwortzeit
Fehlerrate
```

**Sinnvolle Vergleichszeiträume:**

- unmittelbar vor der Störung,
- während der Störung,
- unmittelbar danach,
- normaler Vergleichszeitraum,
- gleiche Uhrzeit an einem störungsfreien Tag,
- Zustand vor und nach einer Maßnahme.

> Ein Messwerkzeug erzeugt selbst Last. Abtastrate, Anzahl der Messwerte und Detailgrad müssen zum System passen.

</details>

---

<details>
<summary><strong>4. Schnellübersicht für Windows, Linux und macOS</strong></summary>

| Aufgabe | Windows | Linux | macOS |
|---|---|---|---|
| Systemlaufzeit | `[RO] (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime` | `[RO] uptime` | `[RO] uptime` |
| Logische Prozessoren | `[RO] (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors` | `[RO] nproc` | `[RO] sysctl -n hw.logicalcpu` |
| Prozessübersicht | `[RO] Get-Process` | `[RO] top` | `[RO] top` |
| Speicherübersicht | `[RO] Get-CimInstance Win32_OperatingSystem` | `[RO] free -h` | `[RO] memory_pressure` |
| Swap | `[RO] Get-CimInstance Win32_PageFileUsage` | `[RO] swapon --show` | `[RO] sysctl vm.swapusage` |
| Datenträgerübersicht | `[RO] Get-Volume` | `[RO] iostat` | `[RO] iostat` |
| Prozesslimits | Betriebssystemspezifisch | `[RO][FILE] cat /proc/<PID>/limits` | `[RO] launchctl limit` |
| Systemprotokolle | `[RO] Get-WinEvent` | `[RO][PRIV] sudo journalctl` | `[RO][PRIV] sudo log show` |

</details>

---

<details>
<summary><strong>5. CPU-Grunddaten unter Windows prüfen</strong></summary>

**Anzahl logischer Prozessoren anzeigen:**

```powershell
[RO] Get-CimInstance Win32_ComputerSystem |
    Select-Object NumberOfProcessors,
                  NumberOfLogicalProcessors
```

**Gesamte CPU-Auslastung als Momentaufnahme:**

```powershell
[RO] Get-CimInstance `
    Win32_PerfFormattedData_PerfOS_Processor `
    -Filter "Name='_Total'" |
    Select-Object Name,
                  PercentProcessorTime,
                  PercentUserTime,
                  PercentPrivilegedTime,
                  PercentIdleTime
```

**Mehrere Messpunkte mit Get-Counter erfassen:**

```powershell
[RO] Get-Counter `
    -Counter '\Processor(_Total)\% Processor Time' `
    -SampleInterval 2 `
    -MaxSamples 5
```

> Die Namen klassischer Windows-Leistungsindikatoren können auf lokalisierten Windows-Systemen übersetzt sein. Falls ein Counterpfad nicht gefunden wird, müssen die auf diesem System vorhandenen Zählersätze ermittelt werden.

**Verfügbare Zählersätze suchen:**

```powershell
[RO] Get-Counter -ListSet * |
    Select-Object CounterSetName |
    Sort-Object CounterSetName
```

</details>

---

<details>
<summary><strong>6. CPU-verbrauchende Windows-Prozesse ermitteln</strong></summary>

**Prozesse nach kumulierter CPU-Zeit sortieren:**

```powershell
[RO] Get-Process |
    Sort-Object CPU -Descending |
    Select-Object -First 15 Id,
                           ProcessName,
                           CPU,
                           StartTime
```

Die Eigenschaft `CPU` enthält die gesamte bisher verbrauchte Prozessorzeit des Prozesses in Sekunden. Sie ist kein momentaner Prozentwert.

**Momentane Prozessauslastung über formatierte Leistungsdaten:**

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfProc_Process |
    Where-Object Name -NotIn "_Total", "Idle" |
    Sort-Object PercentProcessorTime -Descending |
    Select-Object -First 15 Name,
                           IDProcess,
                           PercentProcessorTime,
                           ThreadCount,
                           WorkingSetPrivate
```

**Bestimmte PID untersuchen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  StartTime,
                  CPU,
                  Threads,
                  HandleCount
```

> Die Prozess-CPU-Ausgabe kann bei mehreren logischen Prozessoren anders skaliert wirken als die gesamte Systemauslastung. Werte müssen im Kontext des verwendeten Messwerkzeugs interpretiert werden.

</details>

---

<details>
<summary><strong>7. Arbeitsspeicher unter Windows prüfen</strong></summary>

**Gesamten und freien physischen Speicher anzeigen:**

```powershell
[RO] Get-CimInstance Win32_OperatingSystem |
    Select-Object @{
        Name="TotalRAM_GiB"
        Expression={[math]::Round($_.TotalVisibleMemorySize / 1MB, 2)}
    }, @{
        Name="FreeRAM_GiB"
        Expression={[math]::Round($_.FreePhysicalMemory / 1MB, 2)}
    }, @{
        Name="FreeVirtualMemory_GiB"
        Expression={[math]::Round($_.FreeVirtualMemory / 1MB, 2)}
    }
```

Die CIM-Werte werden hier von KiB in GiB umgerechnet.

**Speicherindikatoren als Momentaufnahme:**

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfOS_Memory |
    Select-Object AvailableMBytes,
                  PercentCommittedBytesInUse,
                  PagesPerSec,
                  PageReadsPerSec,
                  PageWritesPerSec,
                  PoolPagedBytes,
                  PoolNonpagedBytes
```

**Mehrere Messpunkte des verfügbaren Speichers:**

```powershell
[RO] Get-Counter `
    -Counter '\Memory\Available MBytes' `
    -SampleInterval 2 `
    -MaxSamples 5
```

> Ein niedriger Wert bei „freiem“ Speicher ist nicht automatisch ein Fehler, weil Betriebssysteme ungenutzten Speicher als Cache verwenden. Verfügbarer Speicher, Paging-Aktivität und Anwendungsfunktion müssen gemeinsam betrachtet werden.

</details>

---

<details>
<summary><strong>8. Speicherverbrauch von Windows-Prozessen prüfen</strong></summary>

**Nach Working Set sortieren:**

```powershell
[RO] Get-Process |
    Sort-Object WorkingSet64 -Descending |
    Select-Object -First 15 Id,
                           ProcessName,
                           @{
                               Name="WorkingSet_MiB"
                               Expression={[math]::Round($_.WorkingSet64 / 1MB, 2)}
                           },
                           @{
                               Name="PrivateMemory_MiB"
                               Expression={[math]::Round($_.PrivateMemorySize64 / 1MB, 2)}
                           }
```

**Bestimmten Prozess untersuchen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  WorkingSet64,
                  PrivateMemorySize64,
                  VirtualMemorySize64,
                  PagedMemorySize64,
                  PeakWorkingSet64
```

| Wert | Bedeutung |
|---|---|
| `WorkingSet64` | Derzeit im physischen Speicher befindliche Seiten |
| `PrivateMemorySize64` | Privat zugeordneter Speicher |
| `VirtualMemorySize64` | Virtueller Adressraum |
| `PagedMemorySize64` | Auslagerungsfähiger Speicher |
| `PeakWorkingSet64` | Bisheriger Höchstwert des Working Sets |

> Virtueller Speicher darf nicht direkt mit physisch belegtem RAM gleichgesetzt werden.

</details>

---

<details>
<summary><strong>9. Windows-Auslagerungsdatei prüfen</strong></summary>

**Nutzung der Auslagerungsdatei anzeigen:**

```powershell
[RO] Get-CimInstance Win32_PageFileUsage |
    Select-Object Name,
                  AllocatedBaseSize,
                  CurrentUsage,
                  PeakUsage
```

Die Größen werden üblicherweise in MiB angegeben.

**Konfiguration der Auslagerungsdatei anzeigen:**

```powershell
[RO] Get-CimInstance Win32_PageFileSetting |
    Select-Object Name,
                  InitialSize,
                  MaximumSize
```

Mögliche Hinweise auf Speicherdruck:

- `PercentCommittedBytesInUse` bleibt sehr hoch,
- verfügbarer Speicher bleibt niedrig,
- Page Reads steigen dauerhaft,
- Anwendungen melden fehlenden virtuellen Speicher,
- Prozesse werden beendet,
- Antwortzeiten verschlechtern sich parallel zur Paging-Aktivität.

> Das Vorhandensein einer verwendeten Auslagerungsdatei ist nicht automatisch ein Fehler. Entscheidend ist eine dauerhaft hohe Paging-Aktivität zusammen mit Leistungsproblemen.

</details>

---

<details>
<summary><strong>10. Windows-Datenträger-I/O prüfen</strong></summary>

**Formatierte Datenträgerleistungsdaten anzeigen:**

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfDisk_PhysicalDisk |
    Where-Object Name -ne "_Total" |
    Select-Object Name,
                  DiskReadsPerSec,
                  DiskWritesPerSec,
                  DiskReadBytesPerSec,
                  DiskWriteBytesPerSec,
                  AvgDiskQueueLength,
                  CurrentDiskQueueLength,
                  PercentDiskTime
```

**Mehrere Messpunkte mit Get-Counter:**

```powershell
[RO] Get-Counter `
    -Counter '\PhysicalDisk(*)\Avg. Disk sec/Read',
             '\PhysicalDisk(*)\Avg. Disk sec/Write',
             '\PhysicalDisk(*)\Current Disk Queue Length' `
    -SampleInterval 2 `
    -MaxSamples 5
```

Auch hier können lokalisierte Leistungsindikatornamen abweichen.

**Zu prüfen:**

- steigt die Warteschlange dauerhaft?
- sind Lese- oder Schreiblatenzen erhöht?
- ist nur ein Datenträger betroffen?
- korreliert die I/O-Last mit dem Dienstfehler?
- erzeugt Sicherung, Virenscan oder Update gleichzeitig Last?
- ist das Volume lokal, virtuell oder netzwerkbasiert?
- meldet das System zusätzlich Datenträgerfehler?

</details>

---

<details>
<summary><strong>11. Windows-Handles und Threads prüfen</strong></summary>

**Gesamtanzahl von Prozessen, Threads und Handles:**

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfOS_System |
    Select-Object Processes, Threads
```

```powershell
[RO] Get-CimInstance Win32_PerfFormattedData_PerfOS_Objects |
    Select-Object Processes,
                  Threads,
                  Events,
                  Mutexes,
                  Sections,
                  Semaphores
```

**Prozesse nach Handleanzahl sortieren:**

```powershell
[RO] Get-Process |
    Sort-Object HandleCount -Descending |
    Select-Object -First 15 Id,
                           ProcessName,
                           HandleCount,
                           @{
                               Name="ThreadCount"
                               Expression={$_.Threads.Count}
                           }
```

**Bestimmten Prozess prüfen:**

```powershell
[RO] Get-Process -Id <PID> |
    Select-Object Id,
                  ProcessName,
                  HandleCount,
                  @{
                      Name="ThreadCount"
                      Expression={$_.Threads.Count}
                  }
```

Ein mögliches Ressourcenleck zeigt sich eher durch kontinuierliches Wachstum als durch einen einzelnen hohen Wert.

</details>

---

<details>
<summary><strong>12. Windows-Protokolle nach Ressourcenfehlern durchsuchen</strong></summary>

**Systemereignisse der letzten zwei Stunden:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = "System"
    StartTime = (Get-Date).AddHours(-2)
    Level     = 1, 2, 3
} |
    Select-Object TimeCreated,
                  ProviderName,
                  Id,
                  LevelDisplayName,
                  Message
```

**System- und Anwendungsereignisse gemeinsam:**

```powershell
[RO][SENS] Get-WinEvent -FilterHashtable @{
    LogName   = "System", "Application"
    StartTime = (Get-Date).AddHours(-2)
} |
    Where-Object Message -Match "memory|resource|disk|paging|quota|handle|thread" |
    Sort-Object TimeCreated |
    Select-Object TimeCreated,
                  LogName,
                  ProviderName,
                  Id,
                  Message
```

> Textfilter hängen von Sprache und Formulierung der Ereignismeldung ab. Anbieter, Ereignis-ID und Zeitfenster sind zuverlässigere zusätzliche Filter.

</details>

---

<details>
<summary><strong>13. CPU und Load Average unter Linux prüfen</strong></summary>

**Systemlaufzeit und Load Average anzeigen:**

```bash
[RO] uptime
```

**Nur Load Average anzeigen:**

```bash
[RO][FILE] cat /proc/loadavg
```

**Anzahl verfügbarer Verarbeitungseinheiten anzeigen:**

```bash
[RO] nproc
```

**Interaktive Prozessübersicht:**

```bash
[RO] top
```

**Nach CPU-Verbrauch sortieren:**

```bash
[RO] ps -eo pid,ppid,user,stat,%cpu,%mem,etime,comm \
  --sort=-%cpu |
  head -n 16
```

**Falls sysstat installiert ist – CPU je Prozessor messen:**

```bash
[RO] mpstat -P ALL 2 5
```

> `mpstat`, `pidstat` und `iostat` gehören häufig zum Paket `sysstat`, sind aber nicht auf jeder Installation vorhanden.

</details>

---

<details>
<summary><strong>14. Linux Load Average richtig interpretieren</strong></summary>

Die drei Load-Average-Werte beziehen sich üblicherweise auf ungefähr:

```text
1 Minute
5 Minuten
15 Minuten
```

Load Average ist nicht dasselbe wie CPU-Prozent. Unter Linux werden dabei auch bestimmte Prozesse in nicht unterbrechbarem Wartezustand berücksichtigt.

**Grobe Einordnung:**

```text
Load Average
geteilt durch
Anzahl verfügbarer CPUs
```

Dies ist nur eine Orientierung.

| Beobachtung | Mögliche Interpretation |
|---|---|
| Hoher Load und hohe CPU-Nutzung | CPU-Sättigung möglich |
| Hoher Load und niedrige CPU-Nutzung | I/O-Wartezustände möglich |
| Kurzzeitig hoher 1-Minuten-Wert | Lastspitze |
| Hohe 1-, 5- und 15-Minuten-Werte | Länger andauernde Belastung |
| Load steigt, Warteschlange wächst | System verarbeitet Arbeit nicht schnell genug |

> Ein Load-Wert von `4` ist auf einem System mit zwei CPUs anders zu bewerten als auf einem System mit 32 CPUs.

</details>

---

<details>
<summary><strong>15. Linux-CPU über mehrere Messpunkte prüfen</strong></summary>

**Systemweite Messreihe mit vmstat:**

```bash
[RO] vmstat 2 5
```

Wichtige Spalten:

| Spalte | Bedeutung |
|---|---|
| `r` | Ausführungsbereite Prozesse |
| `b` | Prozesse in blockiertem Zustand |
| `us` | CPU-Zeit im Benutzerbereich |
| `sy` | CPU-Zeit im Kernelbereich |
| `id` | Leerlauf |
| `wa` | I/O-Wartezeit |
| `st` | Durch Hypervisor entnommene CPU-Zeit |
| `si` | Swap-In |
| `so` | Swap-Out |

> Die erste Zeile von `vmstat` kann Durchschnittswerte seit dem Systemstart darstellen. Für eine aktuelle Bewertung sind die folgenden Intervallzeilen wichtiger.

**Bestimmten Prozess mit installiertem pidstat beobachten:**

```bash
[RO] pidstat -p <PID> 2 5
```

**Alle Prozesse mit hoher CPU-Aktivität beobachten:**

```bash
[RO] pidstat -u 2 5
```

</details>

---

<details>
<summary><strong>16. Arbeitsspeicher unter Linux prüfen</strong></summary>

**Lesbare Speicherübersicht:**

```bash
[RO] free -h
```

**Kernel-Speicherinformationen:**

```bash
[RO][FILE] cat /proc/meminfo
```

Wichtige Werte:

| Wert | Bedeutung |
|---|---|
| `MemTotal` | Gesamter physischer Speicher |
| `MemFree` | Vollständig ungenutzter Speicher |
| `MemAvailable` | Schätzung des für neue Anwendungen verfügbaren Speichers |
| `Buffers` | Pufferspeicher |
| `Cached` | Dateicache |
| `SwapTotal` | Gesamter Swap |
| `SwapFree` | Freier Swap |
| `Dirty` | Noch nicht auf Datenträger geschriebene Seiten |
| `Slab` | Kernel-Datenstrukturen |

> Für die praktische Bewertung ist `MemAvailable` meist aussagekräftiger als `MemFree`, weil Linux freien RAM bewusst als Cache nutzt.

</details>

---

<details>
<summary><strong>17. Linux-Prozesse nach Speicherverbrauch untersuchen</strong></summary>

**Nach residentem Speicher sortieren:**

```bash
[RO] ps -eo pid,ppid,user,stat,%cpu,%mem,rss,vsz,etime,comm \
  --sort=-rss |
  head -n 16
```

**Bestimmten Prozess anzeigen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,pid,ppid,stat,%cpu,%mem,rss,vsz,etime,cmd
```

**Detaillierte Prozessspeicherwerte:**

```bash
[RO][FILE][SENS] cat "/proc/<PID>/status"
```

Relevant sind unter anderem:

```text
VmPeak
VmSize
VmHWM
VmRSS
RssAnon
RssFile
VmSwap
Threads
```

| Wert | Bedeutung |
|---|---|
| `VmSize` | Virtueller Adressraum |
| `VmRSS` | Residenter physischer Speicher |
| `VmHWM` | Bisheriger Höchstwert des residenten Speichers |
| `VmSwap` | Für den Prozess ausgelagerter Speicher |
| `Threads` | Threadanzahl |

</details>

---

<details>
<summary><strong>18. Swap und Paging unter Linux prüfen</strong></summary>

**Aktive Swap-Bereiche anzeigen:**

```bash
[RO] swapon --show
```

**Gesamtnutzung anzeigen:**

```bash
[RO] free -h
```

**Swap-Aktivität über mehrere Messpunkte:**

```bash
[RO] vmstat 2 5
```

Relevant:

| Spalte | Bedeutung |
|---|---|
| `si` | Von Swap eingelesene Daten |
| `so` | In Swap geschriebene Daten |

**Bewertung:**

- verwendeter Swap allein beweist keinen aktuellen Engpass,
- dauerhaft hohe Werte bei `si` und `so` weisen auf aktiven Speicherdruck hin,
- gleichzeitige hohe I/O-Wartezeit kann die Anwendung stark verlangsamen,
- einzelne Prozesse können einen großen Teil des Speichers belegen,
- ein Container kann sein eigenes Speicherlimit erreichen, obwohl der Host noch freien RAM besitzt.

</details>

---

<details>
<summary><strong>19. Linux-Datenträger-I/O prüfen</strong></summary>

**Grundlegende Datenträgerstatistik:**

```bash
[RO] iostat
```

**Falls sysstat installiert ist – erweiterte Messreihe:**

```bash
[RO] iostat -xz 2 5
```

Wichtige Felder können je nach Version enthalten:

| Feld | Bedeutung |
|---|---|
| `r/s` | Lesevorgänge pro Sekunde |
| `w/s` | Schreibvorgänge pro Sekunde |
| `rkB/s` | Gelesene KiB pro Sekunde |
| `wkB/s` | Geschriebene KiB pro Sekunde |
| `await` | Durchschnittliche Wartezeit |
| `aqu-sz` | Durchschnittliche Warteschlangenlänge |
| `%util` | Anteil der Zeit mit aktiven I/O-Anfragen |

**Prozessbezogene I/O-Aktivität mit pidstat:**

```bash
[RO] pidstat -d 2 5
```

> `%util` und Warteschlangenwerte müssen zur Datenträgerart und Speicherarchitektur passend bewertet werden. RAID, SSD, SAN und virtuelle Datenträger verhalten sich unterschiedlich.

</details>

---

<details>
<summary><strong>20. Linux Pressure Stall Information prüfen</strong></summary>

Auf unterstützten Linux-Kernels stehen Druckinformationen unter `/proc/pressure` bereit.

**CPU-Druck:**

```bash
[RO][FILE] cat /proc/pressure/cpu
```

**Speicherdruck:**

```bash
[RO][FILE] cat /proc/pressure/memory
```

**I/O-Druck:**

```bash
[RO][FILE] cat /proc/pressure/io
```

Mögliche Zeilen:

```text
some
full
```

| Wert | Bedeutung |
|---|---|
| `some` | Mindestens eine Aufgabe wurde durch Ressourcenmangel verzögert |
| `full` | Alle nicht im Leerlauf befindlichen Aufgaben waren gleichzeitig verzögert |
| `avg10` | Durchschnitt der letzten 10 Sekunden |
| `avg60` | Durchschnitt der letzten 60 Sekunden |
| `avg300` | Durchschnitt der letzten 300 Sekunden |
| `total` | Kumulierte Verzögerungszeit in Mikrosekunden |

> Fehlen die Dateien, unterstützt oder aktiviert das System diese Schnittstelle möglicherweise nicht.

</details>

---

<details>
<summary><strong>21. Linux-Dateideskriptor- und Prozessgrenzen prüfen</strong></summary>

**Grenzwerte eines laufenden Prozesses:**

```bash
[RO][FILE] cat "/proc/<PID>/limits"
```

Besonders relevant:

```text
Max open files
Max processes
Max locked memory
Max address space
Max core file size
```

**Anzahl geöffneter Dateideskriptoren:**

```bash
[RO][PRIV] sudo find "/proc/<PID>/fd" \
  -mindepth 1 \
  -maxdepth 1 \
  -printf '.' |
    wc -c
```

**systemd-Grenzwerte anzeigen:**

```bash
[RO] systemctl show "<DIENST>" \
  --property=LimitNOFILE,LimitNPROC,TasksCurrent,TasksMax,MemoryCurrent,MemoryMax,CPUQuotaPerSecUSec
```

**Aktuelle Shell-Grenzen anzeigen:**

```bash
[RO] ulimit -a
```

> `ulimit -a` zeigt die Grenzen der aktuellen Shell und nicht automatisch die Grenzen eines bereits laufenden Dienstes.

</details>

---

<details>
<summary><strong>22. Linux-Protokolle nach Ressourcenfehlern durchsuchen</strong></summary>

**Warnungen und Fehler des aktuellen Systemstarts:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -b \
  -p warning \
  --no-pager
```

**Kernelmeldungen nach Speicherproblemen durchsuchen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -k \
  -b \
  --no-pager |
    grep -i -E -- "out of memory|oom|killed process|memory cgroup"
```

**Nach I/O- und Dateisystemproblemen suchen:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -k \
  -b \
  --no-pager |
    grep -i -E -- "i/o error|filesystem|read-only|blocked for more than"
```

**Dienstprotokoll im Störungszeitraum:**

```bash
[RO][SENS][PRIV] sudo journalctl \
  -u "<DIENST>" \
  --since "2026-07-31 09:10:00" \
  --until "2026-07-31 09:20:00" \
  --no-pager
```

</details>

---

<details>
<summary><strong>23. CPU und Load Average unter macOS prüfen</strong></summary>

**Systemlaufzeit und Load Average:**

```bash
[RO] uptime
```

**Logische und physische CPUs:**

```bash
[RO] sysctl -n hw.logicalcpu
```

```bash
[RO] sysctl -n hw.physicalcpu
```

**Interaktive Übersicht nach CPU-Nutzung:**

```bash
[RO] top -o cpu
```

**Fünf Messungen im Abstand von zwei Sekunden:**

```bash
[RO] top \
  -l 5 \
  -s 2 \
  -o cpu \
  -stats pid,command,cpu,mem,threads,state,time
```

**Bestimmten Prozess beobachten:**

```bash
[RO] top \
  -l 5 \
  -s 2 \
  -pid <PID> \
  -stats pid,command,cpu,mem,threads,state,time
```

> Bei `top -l` kann die erste CPU-Messung ungeeignet sein, weil zur Prozentberechnung noch kein vollständiges vorheriges Intervall vorliegt.

</details>

---

<details>
<summary><strong>24. Speicher unter macOS prüfen</strong></summary>

**Speicherdruck anzeigen:**

```bash
[RO] memory_pressure
```

**Virtuelle Speicherstatistik:**

```bash
[RO] vm_stat
```

**Gesamten physischen Speicher anzeigen:**

```bash
[RO] sysctl -n hw.memsize
```

**Swap-Nutzung anzeigen:**

```bash
[RO] sysctl vm.swapusage
```

**Prozesse nach Speicherverbrauch sortieren:**

```bash
[RO] ps -Amcwwxo pid,ppid,user,state,%cpu,%mem,rss,vsz,etime,command
```

**Bestimmten Prozess anzeigen:**

```bash
[RO][SENS] ps -p <PID> \
  -o user,pid,ppid,state,%cpu,%mem,rss,vsz,etime,command
```

> macOS verwaltet Arbeitsspeicher unter anderem durch Cache, Kompression und Swap. „Freier Speicher“ allein ist deshalb weniger aussagekräftig als Speicherdruck, Swap-Aktivität und Anwendungsreaktion.

</details>

---

<details>
<summary><strong>25. vm_stat unter macOS interpretieren</strong></summary>

`vm_stat` zeigt Speicherwerte in Seiten an. Die Seitengröße wird in der ersten Ausgabezeile genannt.

Wichtige Werte können sein:

| Wert | Bedeutung |
|---|---|
| `Pages free` | Freie Seiten |
| `Pages active` | Aktiv verwendete Seiten |
| `Pages inactive` | Inaktive, möglicherweise wiederverwendbare Seiten |
| `Pages speculative` | Spekulativ geladene Seiten |
| `Pages wired down` | Nicht auslagerbarer Speicher |
| `Pages occupied by compressor` | Durch Speicherkompression belegte Seiten |
| `Pageins` | Vom Datenträger eingelesene Seiten |
| `Pageouts` | Auf Datenträger ausgelagerte Seiten |
| `Swapins` | Aus Swap eingelesene Seiten |
| `Swapouts` | In Swap geschriebene Seiten |

> Viele Werte sind kumuliert seit dem Systemstart. Für aktuelle Aktivität müssen Messungen über einen definierten Zeitraum verglichen werden.

</details>

---

<details>
<summary><strong>26. Datenträger-I/O unter macOS prüfen</strong></summary>

**Datenträgerübersicht:**

```bash
[RO] iostat
```

**Fünf Messungen im Abstand von zwei Sekunden:**

```bash
[RO] iostat -w 2 -c 5
```

**CPU- und Datenträgerstatistik ausführlicher anzeigen:**

```bash
[RO] iostat -d -c 5 -w 2
```

**Prozessbezogene Beobachtung mit top:**

```bash
[RO] top \
  -l 5 \
  -s 2 \
  -o cpu \
  -stats pid,command,cpu,mem,purg,cmprs,pageins,faults
```

Zu prüfen:

- steigt Datenträgeraktivität während der Störung?
- tritt gleichzeitig Speicherdruck auf?
- verursacht ein anderer Prozess hohe I/O-Last?
- ist das Ziel ein internes, externes oder Netzwerkvolume?
- gibt es Dateisystem- oder Hardwaremeldungen?
- wird gleichzeitig gesichert, indiziert oder aktualisiert?

</details>

---

<details>
<summary><strong>27. Prozess- und Dateigrenzen unter macOS prüfen</strong></summary>

**Grenzwerte von launchd anzeigen:**

```bash
[RO] launchctl limit
```

**Grenzwerte der aktuellen Shell anzeigen:**

```bash
[RO] ulimit -a
```

**Offene Ressourcen eines Prozesses anzeigen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -p <PID>
```

**Anzahl der ausgegebenen offenen Ressourcen grob zählen:**

```bash
[RO][SENS][PRIV] sudo lsof -nP -p <PID> |
    wc -l
```

Die Kopfzeile von `lsof` wird dabei mitgezählt.

**Threadanzahl anzeigen:**

```bash
[RO] ps -M -p <PID>
```

> Die Grenzwerte einer Shell sind nicht automatisch mit denen eines launchd-Dienstes identisch. Für den Dienst müssen launchd-Konfiguration, Prozesskontext und tatsächlicher Verbrauch berücksichtigt werden.

</details>

---

<details>
<summary><strong>28. macOS-Protokolle nach Ressourcenproblemen prüfen</strong></summary>

**Fehler und Faults der letzten Stunde:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'messageType == error OR messageType == fault' \
  --style compact \
  --no-pager
```

**Dienstprozess filtern:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'process == "<PROZESS>"' \
  --style compact \
  --no-pager
```

**Nach ressourcenbezogenen Meldungstexten suchen:**

```bash
[RO][SENS][PRIV] sudo log show \
  --last 1h \
  --predicate 'eventMessage CONTAINS[c] "memory" OR eventMessage CONTAINS[c] "resource" OR eventMessage CONTAINS[c] "disk"' \
  --style compact \
  --no-pager
```

> Textfilter sind nur eine Ergänzung. Prozess, Zeitfenster, Subsystem und konkrete Fehlermeldung müssen ebenfalls berücksichtigt werden.

</details>

---

<details>
<summary><strong>29. CPU-Engpass systematisch erkennen</strong></summary>

**Belastbare Hinweise:**

- CPU-Auslastung bleibt über längere Zeit hoch,
- ausführungsbereite Prozesse warten,
- Antwortzeiten steigen gleichzeitig,
- Anwendungswarteschlange wächst,
- Timeouts treten auf,
- ein bestimmter Prozess oder Thread verursacht den Großteil der Last,
- virtueller Host meldet hohe CPU-Steal- oder Ready-Zeit,
- CPU-Limit eines Containers wird erreicht.

**Mögliche Ursachen:**

- regulär hohe Benutzerlast,
- Endlosschleife,
- fehlerhafte Abfrage,
- Kompression oder Verschlüsselung,
- Virenscan,
- Sicherung,
- Softwareupdate,
- zu viele Prozesse oder Threads,
- zu niedriges Containerlimit,
- fehlende Hardwarebeschleunigung.

**Nicht ausreichend als Beweis:**

```text
Ein einzelner Messwert von 100 %
```

</details>

---

<details>
<summary><strong>30. Arbeitsspeicherengpass systematisch erkennen</strong></summary>

**Belastbare Hinweise:**

- verfügbarer Speicher bleibt dauerhaft niedrig,
- Paging oder Swapping ist kontinuierlich aktiv,
- Speicherdruck steigt,
- Antwortzeiten steigen parallel,
- Prozesse werden durch Speichermangel beendet,
- Anwendung meldet Allokationsfehler,
- Prozessspeicher wächst kontinuierlich,
- Container erreicht `MemoryMax` oder sein Plattformlimit,
- Cache kann nicht ausreichend zurückgewonnen werden.

**Mögliche Ursachen:**

- Speicherleck,
- zu großer Cache,
- unerwartet viele Sitzungen,
- zu große Datenmenge,
- mehrere speicherintensive Dienste,
- zu kleines VM- oder Containerlimit,
- fehlerhafte Heap-Konfiguration,
- fehlende Begrenzung von Workerprozessen.

> Ein Dienstneustart kann den Speicherverbrauch kurzfristig reduzieren, beweist aber nicht, dass die Ursache beseitigt wurde.

</details>

---

<details>
<summary><strong>31. I/O-Engpass systematisch erkennen</strong></summary>

**Belastbare Hinweise:**

- I/O-Wartezeiten steigen,
- Warteschlange bleibt gefüllt,
- Prozesse verbleiben im Wartezustand,
- Datenbankabfragen werden langsam,
- Schreibvorgänge blockieren,
- gleichzeitig erscheinen I/O- oder Dateisystemfehler,
- Netzwerkstorage zeigt hohe Latenz,
- Sicherung oder Indizierung erzeugt konkurrierende Last.

**Mögliche Ursachen:**

- langsamer oder fehlerhafter Datenträger,
- RAID-Rebuild,
- defekter Datenträger,
- überlastetes SAN oder NAS,
- hoher Speicherdruck und Paging,
- ungeeignete Datenbankabfrage,
- fehlender Cache,
- Sicherung oder Virenscan,
- zu viele parallele Schreibvorgänge,
- Volume- oder IOPS-Limit einer Cloudplattform.

> Hoher Datendurchsatz kann normal sein. Ein Engpass zeigt sich durch Wartezeit, Warteschlange und beeinträchtigte Anwendung.

</details>

---

<details>
<summary><strong>32. Ressourcenleck erkennen</strong></summary>

Ein Ressourcenleck wird durch eine Zeitreihe sichtbar.

Mögliche Lecks:

- Arbeitsspeicher,
- Handles,
- Dateideskriptoren,
- Threads,
- Netzwerkverbindungen,
- temporäre Dateien,
- Datenbankverbindungen,
- Warteschlangeneinträge.

**Typisches Muster:**

```text
Dienststart          niedriger Verbrauch
nach 1 Stunde        höherer Verbrauch
nach 6 Stunden       weiter gestiegen
nach 24 Stunden      Grenzwert erreicht
nach Dienstneustart  wieder niedriger Verbrauch
```

**Nachweisstrategie:**

1. gleiche Messgröße verwenden,
2. regelmäßige Zeitpunkte erfassen,
3. Last und Benutzerzahl mit dokumentieren,
4. Prozessneustarts berücksichtigen,
5. Grenzwert und Fehlereintritt bestimmen,
6. Herstellerdiagnose oder Profiler kontrolliert einsetzen.

> Wachstum kann durch einen vorgesehenen Cache entstehen. Ein Leck ist erst wahrscheinlich, wenn Ressourcen trotz abgeschlossener Arbeit nicht angemessen freigegeben werden und der Verbrauch problematisch weiter steigt.

</details>

---

<details>
<summary><strong>33. Virtualisierung und Containerlimits berücksichtigen</strong></summary>

Ein Gastbetriebssystem kann normale Hostwerte anzeigen, obwohl die Virtualisierungsplattform Ressourcen begrenzt.

Zu prüfen:

- zugewiesene virtuelle CPUs,
- CPU-Limit oder CPU-Anteile,
- CPU-Steal- beziehungsweise Ready-Zeit,
- zugesicherter und maximaler RAM,
- Memory Ballooning,
- Host-Swapping,
- IOPS- und Durchsatzlimits,
- Container-CPU-Quota,
- Container-Speicherlimit,
- Prozess- beziehungsweise PID-Limit,
- gemeinsam verwendete Hostressourcen,
- konkurrierende virtuelle Maschinen oder Container.

**Typische Fehlinterpretation:**

> „Der Host hat noch freien RAM, deshalb kann der Container keinen Speichermangel haben.“

Ein Container kann sein eigenes Limit erreichen, obwohl der Host noch freie Ressourcen besitzt.

</details>

---

<details>
<summary><strong>34. Engpass anhand einer Vergleichsmatrix eingrenzen</strong></summary>

| CPU | RAM | I/O-Wartezeit | Mögliche Richtung |
|---:|---:|---:|---|
| Hoch | Normal | Niedrig | CPU-intensive Verarbeitung |
| Niedrig | Knapp | Hoch | Paging oder Speicherdruck |
| Niedrig | Normal | Hoch | Datenträger- oder Netzwerkstorage |
| Hoch | Knapp | Hoch | Gesamtsystem überlastet |
| Niedrig | Normal | Niedrig | Externes Backend, Sperre oder Anwendung |
| Normal | Verbrauch steigt | Zunehmend | Mögliches Speicherleck |
| Normal | Normal | Normal | Anwendungs-, Netzwerk- oder Konfigurationsfehler |

Diese Matrix ist eine Eingrenzungshilfe und kein automatischer Ursachenbeweis.

</details>

---

<details>
<summary><strong>35. Typische Fehlinterpretationen</strong></summary>

| Fehlinterpretation | Richtige Bewertung |
|---|---|
| „100 Prozent CPU bedeutet immer einen Fehler.“ | Kurze oder produktive Vollauslastung kann normal sein |
| „Freier RAM ist niedrig, also fehlt Speicher.“ | Cache und verfügbarer Speicher müssen berücksichtigt werden |
| „Swap wird verwendet, also ist das System überlastet.“ | Aktuelle Swap-Aktivität und Speicherdruck sind entscheidend |
| „Hoher Datendurchsatz bedeutet I/O-Engpass.“ | Wartezeit und Warteschlange sind entscheidender |
| „Load Average entspricht CPU-Prozent.“ | Load berücksichtigt unter Linux weitere Wartezustände |
| „Die erste vmstat-Zeile zeigt die aktuelle Last.“ | Sie kann Durchschnittswerte seit dem Start enthalten |
| „Get-Process CPU ist der aktuelle Prozentwert.“ | Es ist kumulierte CPU-Zeit |
| „Virtueller Speicher ist vollständig belegter RAM.“ | Virtueller Adressraum und residenter Speicher unterscheiden sich |
| „Ein Neustart behebt das Ressourcenproblem.“ | Er kann Zähler und Verbrauch nur vorübergehend zurücksetzen |
| „Der Host hat Ressourcen, also hat der Container sie ebenfalls.“ | Container und VM können eigene Limits besitzen |

</details>

---

<details>
<summary><strong>36. Dokumentationsvorlage für Ressourcenengpässe</strong></summary>

```text
Störung:
Server:
Dienst:
Prozess und PID:
Betriebssystem:
Virtualisiert beziehungsweise containerisiert:
Messzeitraum:
Abtastintervall:
CPU gesamt:
CPU des Prozesses:
Load Average:
Verfügbarer Arbeitsspeicher:
Speicher des Prozesses:
Swap- beziehungsweise Paging-Aktivität:
Datenträgerlatenz:
Datenträgerwarteschlange:
Dateideskriptor- beziehungsweise Handleanzahl:
Threadanzahl:
Konfigurierte Limits:
Anwendungsantwortzeit:
Fehlerrate:
Gleichzeitige Benutzer oder Aufgaben:
Relevante Protokollmeldung:
Vergleichswert:
Bewertung:
Nächster Prüfschritt:
```

</details>

---

<details>
<summary><strong>37. Checkliste zur Ressourcenanalyse</strong></summary>

```text
[ ] Störungszeitraum genau bestimmt
[ ] System- und Prozesswerte getrennt erfasst
[ ] Mehrere Messpunkte aufgenommen
[ ] Normalen Vergleichszeitraum bestimmt
[ ] Anzahl logischer CPUs berücksichtigt
[ ] CPU-Auslastung und Warteschlange geprüft
[ ] Load Average richtig eingeordnet
[ ] Verfügbaren Arbeitsspeicher geprüft
[ ] Prozessspeicher geprüft
[ ] Paging beziehungsweise Swapping geprüft
[ ] Speicherdruck berücksichtigt
[ ] Datenträgerdurchsatz geprüft
[ ] I/O-Wartezeit und Warteschlange geprüft
[ ] Speicherplatz und Dateisystem grob geprüft
[ ] Handle- beziehungsweise Dateideskriptoranzahl geprüft
[ ] Thread- und Prozessgrenzen geprüft
[ ] Ressourcenlecks über Zeitreihe geprüft
[ ] Betriebssystemprotokolle geprüft
[ ] Anwendungsprotokolle geprüft
[ ] VM- und Containerlimits berücksichtigt
[ ] Gleichzeitige Sicherungen und Updates berücksichtigt
[ ] Messwerte mit Antwortzeit und Fehlerrate korreliert
[ ] Noch keine ungeprüfte Limitänderung durchgeführt
[ ] Ursache und nächster Schritt dokumentiert
```

</details>

---

**Bewertung des Ergebnisses**

| Ergebnis | Nächster Schritt |
|---|---|
| CPU dauerhaft gesättigt | Verursachenden Prozess, Threads und Arbeitslast untersuchen |
| Hoher Load bei niedriger CPU | I/O-Wartezustände und blockierte Prozesse prüfen |
| Speicherdruck und aktives Swapping | Prozessspeicher, Limits und mögliches Leck untersuchen |
| Prozessverbrauch steigt kontinuierlich | Zeitreihe und Herstellerdiagnose erstellen |
| Datenträgerlatenz erhöht | Datenträger, Dateisystem, Storage und konkurrierende Last prüfen |
| Dateideskriptor- oder Handlegrenze erreicht | Leck, Grenzwert und benötigte Kapazität untersuchen |
| Containerlimit erreicht | Sollressourcen und Plattformkonfiguration prüfen |
| Host überlastet | Andere VMs, Container und Hostprozesse berücksichtigen |
| Ressourcenwerte normal | Abhängigkeiten, Sperren, Netzwerk und Anwendung untersuchen |
| Speicherplatz oder Dateisystem auffällig | Mit Seite 4.11 detailliert weiterprüfen |

---

**Merksatz**

> **Ein Ressourcenengpass wird nicht durch einen hohen Wert bewiesen, sondern durch dauerhaftes Warten, erreichte Grenzen und eine gleichzeitig beeinträchtigte Dienstfunktion.**

---

**Weiterführende Quellen**

- [Microsoft Learn – Get-Counter](https://learn.microsoft.com/powershell/module/microsoft.powershell.diagnostics/get-counter)
- [Microsoft Learn – Get-Process](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-process)
- [Microsoft Learn – Get-CimInstance](https://learn.microsoft.com/powershell/module/cimcmdlets/get-ciminstance)
- [Microsoft Learn – Win32_Process](https://learn.microsoft.com/windows/win32/cimwin32prov/win32-process)
- [Microsoft Learn – Windows-Leistungsüberwachung](https://learn.microsoft.com/windows-server/administration/windows-commands/typeperf)
- [Linux-Handbuch – proc_loadavg](https://man7.org/linux/man-pages/man5/proc_loadavg.5.html)
- [Linux-Handbuch – proc_meminfo](https://man7.org/linux/man-pages/man5/proc_meminfo.5.html)
- [Linux-Handbuch – proc_pid_limits](https://man7.org/linux/man-pages/man5/proc_pid_limits.5.html)
- [Linux-Handbuch – proc_pressure](https://man7.org/linux/man-pages/man5/proc_pressure.5.html)
- [systemd – systemd.resource-control](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html)
- [Apple – top-Handbuchseite](https://keith.github.io/xcode-man-pages/top.1.html)
- [Apple – vm_stat-Handbuchseite](https://keith.github.io/xcode-man-pages/vm_stat.1.html)
- [Apple – iostat-Handbuchseite](https://keith.github.io/xcode-man-pages/iostat.8.html)
- [Apple – launchctl-Handbuchseite](https://keith.github.io/xcode-man-pages/launchctl.1.html)