Warum der Kernel Speicher auslagert, obwohl free -h Reserven zeigt
Mehrere Gigabyte Swap-Nutzung bei gleichzeitig reichlich freiem Arbeitsspeicher in free -h wirkt paradox, ist aber meistens proaktives, gewolltes Kernel-Verhalten und kein Fehler. Dieser Leitfaden zeigt, wie man mit Pressure Stall Information, vmstat und smaps zwischen harmlosem und tatsächlich problematischem Swapping unterscheidet, welche Rolle Swappiness wirklich spielt und wann MySQL-Buffer-Pool-Konfiguration die eigentliche Ursache ist.
Inhaltsverzeichnis
- 1. Warum Swap-Nutzung bei freiem RAM kein Widerspruch ist
- 2. free -h richtig lesen: verfügbar ist nicht gleich frei
- 3. vmstat und si/so: Aktivität statt Bestand messen
- 4. Pressure Stall Information: Den echten Speicherdruck messen
- 5. Swappiness richtig verstehen und einordnen
- 6. Mit smaps herausfinden, was tatsächlich ausgelagert wurde
- 7. MySQL und der Buffer Pool: Ein häufiger Sonderfall
- 8. cgroup-v2 Memory Pressure für Container-Workloads
- 9. Normales vs. problematisches Swapping im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum Swap-Nutzung bei freiem RAM kein Widerspruch ist
Der Anblick von mehreren Gigabyte belegtem Swap in free -h, während gleichzeitig reichlich freier Arbeitsspeicher gemeldet wird, wirkt auf den ersten Blick wie ein Fehler im System. Tatsächlich ist dieses Verhalten in den meisten Fällen beabsichtigt: Der Linux-Kernel lagert selten genutzte Speicherseiten proaktiv aus, sobald sie längere Zeit nicht angefasst wurden, um den dadurch gewonnenen physischen Speicher für den Page-Cache und aktiv genutzte Anwendungsdaten verfügbar zu machen. Diese Strategie folgt der Grundannahme, dass ungenutzter RAM verschwendeter RAM ist, und priorisiert aktive Daten gegenüber selten gebrauchtem, aber weiterhin allokiertem Speicher.
Das eigentliche Problem entsteht erst, wenn genau diese ausgelagerten Seiten kurz darauf wieder gebraucht werden und der Kernel sie unter Zeitdruck von der deutlich langsameren Swap-Partition zurückholen muss. Diese Situation, bekannt als Thrashing, äußert sich als spürbare Latenz und hohe I/O-Wartezeiten, obwohl free -h nach wie vor ausreichend freien Speicher anzeigt. Die zentrale Herausforderung bei der Diagnose liegt deshalb nicht in der Feststellung, dass Swap genutzt wird, sondern in der Unterscheidung zwischen harmlosem, proaktivem Auslagern und tatsächlich schädlichem, wiederholtem Thrashing.
2. free -h richtig lesen: verfügbar ist nicht gleich frei
Ein häufiger Interpretationsfehler bei free -h ist die Verwechslung der Spalten free und available. Die Spalte free zeigt komplett ungenutzten Speicher, der weder für Anwendungen noch für den Page-Cache reserviert ist, während available zusätzlich den Speicher einschließt, der aktuell im Page-Cache liegt, aber bei Bedarf sofort und ohne Performance-Einbußen freigegeben werden kann. Ein niedriger free-Wert bei hohem available-Wert ist völlig normal und zeigt lediglich, dass der Kernel den Speicher effizient für Caching nutzt, nicht dass ein Engpass droht.
Für die Bewertung der Swap-Nutzung ist entscheidend, die used-Spalte der Swap-Zeile über die Zeit zu beobachten statt einen einzelnen Wert zu bewerten. Ein seit Tagen stabiler Swap-Wert, der sich nicht verändert, deutet auf länger zurückliegendes, einmaliges Auslagern hin und ist meist unproblematisch. Ein Swap-Wert, der kontinuierlich wächst und gleichzeitig mit steigender CPU-Zeit im %wa-Feld (I/O-Wartezeit) von top einhergeht, ist dagegen ein klares Warnsignal für aktives, belastendes Swapping, das die Anwendungsperformance tatsächlich beeinträchtigt.
# free vs. available — the distinction that matters
free -h
# total used free shared buff/cache available
# Mem: 31Gi 18Gi 1.2Gi 412Mi 12Gi 13Gi
# Swap: 8.0Gi 2.1Gi 5.9Gi
# A stable swap value that hasn't changed in days is usually harmless
# Log it over time to distinguish a one-time event from ongoing pressure
watch -n 300 'free -h | grep Swap'
3. vmstat und si/so: Aktivität statt Bestand messen
Während free -h nur einen Momentzustand zeigt, liefert vmstat 1 die tatsächliche Swap-Aktivität in Echtzeit über die Spalten si (swap in, Seiten die von der Swap-Partition zurück in den RAM geladen werden) und so (swap out, Seiten die neu ausgelagert werden). Dauerhaft hohe Werte in beiden Spalten gleichzeitig sind das entscheidende Signal für Thrashing: Der Kernel lagert Seiten aus und muss sie kurz darauf wieder zurückholen, was auf einen echten Speicherengpass hindeutet, bei dem der verfügbare RAM für die aktive Arbeitslast schlicht nicht ausreicht.
Gelegentliche kurze Spitzen in so ohne entsprechende si-Aktivität sind dagegen unbedenklich und entsprechen genau dem proaktiven Auslagern selten genutzter Seiten aus dem vorherigen Abschnitt. Die Faustregel: Ein einmaliger Ausschlag in so gefolgt von Stille ist normal, ein wiederkehrendes Muster aus si und so im Wechsel über mehrere Minuten ist ein Alarmsignal, das eine tiefere Untersuchung der Speicheranforderungen rechtfertigt.
# Live view of swap in/out activity, refreshed every second
vmstat 1 10
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 2 1 2150400 125600 45200 12800000 0 0 120 340 1200 2400 12 4 82 2 0
# 3 4 2151200 118400 45200 12790000 45 180 890 1200 1800 3100 18 9 55 18 0
# ^^^ ^^^ — sustained si+so = real thrashing
# Aggregate view without the noise: only si/so columns over time
vmstat 1 60 | awk '{print $7, $8}'
4. Pressure Stall Information: Den echten Speicherdruck messen
Pressure Stall Information (PSI), verfügbar seit Kernel 4.20 unter /proc/pressure/memory, ist das präziseste verfügbare Werkzeug, um Speicherdruck direkt zu quantifizieren, statt ihn aus Indizien wie Swap-Nutzung abzuleiten. PSI misst, wie viel Prozent der Zeit mindestens ein Prozess (some) beziehungsweise alle Prozesse gleichzeitig (full) durch fehlenden Speicher blockiert waren, aggregiert über 10 Sekunden, 60 Sekunden und 5 Minuten. Ein full avg10-Wert nahe Null bedeutet, dass trotz Swap-Nutzung praktisch kein Prozess durch Speicherknappheit spürbar ausgebremst wurde, was die zuvor beobachtete Swap-Aktivität als unproblematisch einordnet.
Steigt der full avg10-Wert dagegen über einen niedrigen einstelligen Prozentbereich, verbringen Anwendungen messbare Zeit blockiert, weil sie auf ausgelagerte Seiten warten, die gerade zurückgeholt werden. Dieser einzelne Wert ersetzt in der Praxis die mühsame manuelle Korrelation zwischen vmstat-Aktivität, Anwendungslatenz und CPU-Wartezeit und sollte der erste Blick bei jedem Verdacht auf ein Swap-Problem sein, noch vor free -h oder vmstat.
# The single most reliable indicator of actual memory pressure
cat /proc/pressure/memory
# some avg10=2.34 avg60=1.87 avg300=0.95 total=48291823
# full avg10=0.12 avg60=0.08 avg300=0.03 total=1204958
# ^^^^^^^^^ — near-zero "full" means no real stalling
# Alert threshold suggestion: full avg10 consistently above 5% warrants investigation
awk '/^full/ {print $2}' /proc/pressure/memory | grep -oP 'avg10=\K[0-9.]+'
5. Swappiness richtig verstehen und einordnen
Der Parameter vm.swappiness (Standardwert meist 60) steuert, wie aggressiv der Kernel Speicherseiten gegenüber dem Page-Cache priorisiert, wenn Speicher knapp wird, nicht ob überhaupt geswapped wird. Ein häufiges Missverständnis ist die Annahme, vm.swappiness=0 deaktiviere Swap vollständig. Tatsächlich bedeutet der Wert 0 seit Kernel 3.5 nur, dass Swap ausschließlich als letztes Mittel genutzt wird, kurz bevor der OOM-Killer eingreifen müsste, während Werte zwischen 1 und 100 die relative Gewichtung zwischen dem Verdrängen von Page-Cache und dem Auslagern von Anwendungsspeicher festlegen.
Für Datenbankserver wie MySQL, bei denen der eigene Buffer Pool bereits die effektivste Cache-Schicht darstellt, ist ein niedrigerer Wert wie vm.swappiness=10 häufig sinnvoll, weil er dem Kernel signalisiert, den Page-Cache stärker zu bevorzugen, statt aktiv genutzten Anwendungsspeicher zugunsten von Dateisystem-Caching auszulagern. Ein Swappiness-Wert allein löst aber kein zugrunde liegendes Kapazitätsproblem, er verschiebt nur, welche Art von Speicher zuerst betroffen ist, wenn der Druck tatsächlich ansteigt.
# /etc/sysctl.d/99-swappiness.conf
# Lower value favors keeping application memory resident,
# at the cost of evicting page cache more aggressively under pressure.
# Recommended starting point for database servers (MySQL/MariaDB).
vm.swappiness = 10
sudo sysctl --system
# Verify the active value
cat /proc/sys/vm/swappiness
6. Mit smaps herausfinden, was tatsächlich ausgelagert wurde
Wenn PSI einen echten Speicherdruck bestätigt, ist der nächste Schritt herauszufinden, welcher Prozess für die ausgelagerten Seiten verantwortlich ist. /proc/[pid]/status liefert mit VmSwap die pro Prozess ausgelagerte Speichermenge, während smem -st swap eine nach Swap-Nutzung sortierte Übersicht aller Prozesse liefert. Ein Prozess mit auffällig hohem VmSwap-Wert im Vergleich zu seinem VmRSS deutet darauf hin, dass ein erheblicher Teil seines Speichers seit längerem nicht aktiv genutzt wurde, was bei einem Datenbankserver oder einem PHP-FPM-Master-Prozess mit selten genutzten, aber allokierten Puffern durchaus normal sein kann.
Für eine noch genauere Analyse zeigt /proc/[pid]/smaps den Swap-Anteil pro einzelnem Memory-Mapping, was hilft, zwischen ausgelagertem Heap-Speicher, ausgelagerten Shared-Memory-Segmenten und ausgelagerten Bibliotheks-Mappings zu unterscheiden. Diese Aufschlüsselung ist besonders wertvoll, wenn der Verdacht besteht, dass eine bestimmte Anwendungskomponente, etwa ein selten genutzter Admin-Bereich einer Magento-Installation, unnötig viel Speicher allokiert, der dann zu Recht ausgelagert wird, statt dass ein echtes Konfigurationsproblem vorliegt.
# Per-process swap usage, sorted highest first
smem -st swap
# PID User Command Swap USS PSS RSS
# 1823 mysql /usr/sbin/mysqld 512.0M 890.2M 920.4M 1024.8M
# 4821 www-data php-fpm: master process 128.4M 12.1M 18.9M 22.4M
# Breakdown of swapped memory within a single process's mappings
grep -B2 "^Swap:" /proc/1823/smaps | grep -A2 "^7f" | head -30
7. MySQL und der Buffer Pool: Ein häufiger Sonderfall
Bei MySQL-Servern ist Swap-Nutzung ein besonders häufiges und gleichzeitig besonders kritisches Thema, weil der InnoDB Buffer Pool bewusst so konfiguriert wird, dass er einen Großteil des verfügbaren RAM belegt, um Festplattenzugriffe zu minimieren. Wird innodb_buffer_pool_size zu großzügig bemessen, etwa bei 80 Prozent des Gesamtspeichers auf einem Server, der zusätzlich PHP-FPM-Worker und andere Dienste betreibt, konkurriert der Buffer Pool aktiv mit diesen Diensten um physischen Speicher, und der Kernel beginnt, selten genutzte Buffer-Pool-Seiten auszulagern.
Das eigentliche Problem dabei: Ausgelagerte Buffer-Pool-Seiten sind für MySQL nutzlos, sobald sie tatsächlich für eine Abfrage gebraucht werden, weil das Zurückholen von der Swap-Partition um Größenordnungen langsamer ist als ein direkter Festplattenzugriff über InnodB selbst gewesen wäre. In diesem Fall ist die Lösung nicht eine Anpassung der Swappiness, sondern eine korrekte Dimensionierung von innodb_buffer_pool_size unter Berücksichtigung aller anderen Dienste auf demselben Server, typischerweise bei 60 bis 70 Prozent des verfügbaren RAM statt einer pauschalen 80-Prozent-Regel ohne Rücksicht auf Nebendienste.
8. cgroup-v2 Memory Pressure für Container-Workloads
In containerisierten Umgebungen liefert cgroup v2 mit memory.pressure dieselbe PSI-Metrik wie das systemweite /proc/pressure/memory, aber isoliert auf die jeweilige Cgroup, was für Docker-Container und systemd-Services mit eigenem Speicherlimit besonders wertvoll ist. Ein Container, der sein memory.max-Limit erreicht, beginnt zu swappen (sofern memory.swap.max nicht auf 0 gesetzt ist) oder wird vom Cgroup-OOM-Killer beendet, unabhängig vom systemweiten Speicherzustand des Hosts. Die systemweite free -h-Ausgabe kann dabei völlig unauffällig aussehen, während ein einzelner Container bereits unter erheblichem internen Speicherdruck steht.
Für Magento-Setups mit mehreren Containern auf demselben Host ist die gezielte Überwachung von memory.pressure pro Cgroup deshalb aussagekräftiger als die systemweite Ansicht, weil sie genau zeigt, welcher einzelne Dienst tatsächlich unter Druck steht, statt einen aggregierten Wert zu liefern, der lokale Engpässe verschleiern kann.
# Per-cgroup memory pressure, isolated from the rest of the host
cat /sys/fs/cgroup/system.slice/docker-<container-id>.scope/memory.pressure
# Current memory limit and swap configuration for a specific cgroup
cat /sys/fs/cgroup/system.slice/docker-<container-id>.scope/memory.max
cat /sys/fs/cgroup/system.slice/docker-<container-id>.scope/memory.swap.max
9. Normales vs. problematisches Swapping im Vergleich
Die folgende Übersicht fasst die wichtigsten Signale zusammen, um zwischen harmlosem und tatsächlich problematischem Swapping zu unterscheiden.
| Signal | Normal | Problematisch |
|---|---|---|
| Swap used (free -h) | Stabil über Tage, keine Veränderung | Kontinuierlich wachsend |
| vmstat si/so | Einmaliger so-Ausschlag, dann Ruhe | Anhaltender si/so-Wechsel |
| PSI full avg10 | Nahe 0 Prozent | Deutlich über 5 Prozent |
| Anwendungslatenz | Unverändert | Spürbar erhöht, korreliert mit so |
Erst wenn mehrere dieser Signale gleichzeitig in die problematische Spalte fallen, insbesondere ein erhöhter PSI-Wert in Kombination mit anhaltender si/so-Aktivität, liegt tatsächliches Thrashing vor, das eine Kapazitätserweiterung oder eine Anpassung der Speicherkonfiguration rechtfertigt. Ein isoliert betrachteter, stabiler Swap-Wert ohne diese begleitenden Signale ist dagegen kein Handlungsbedarf, sondern normales, effizientes Kernel-Verhalten.
Mironsoft
Linux-Speicheranalyse und Datenbank-Tuning für Magento-Infrastruktur
Swap-Alarme ohne echten Speicherdruck?
Wir analysieren eure Speichernutzung mit PSI und vmstat, unterscheiden harmloses von tatsächlich problematischem Swapping und dimensionieren MySQL Buffer Pool sowie Swappiness passend zu eurer realen Arbeitslast.
Speicherdruck-Audit
PSI-basierte Analyse, ob Swap-Nutzung tatsächlich Anwendungen ausbremst
MySQL-Tuning
Buffer-Pool-Dimensionierung unter Berücksichtigung aller Dienste auf dem Server
Kapazitätsplanung
Reale Engpässe von harmlosem, proaktivem Auslagern zuverlässig trennen
10. Zusammenfassung
Hohe Swap-Nutzung trotz freiem RAM in free -h ist in den meisten Fällen kein Fehler, sondern proaktives Kernel-Verhalten, das selten genutzte Speicherseiten zugunsten von Page-Cache und aktiv genutzten Daten auslagert. Die entscheidende Frage ist nicht, ob Swap genutzt wird, sondern ob dieses Auslagern tatsächlich zu spürbarem Thrashing führt. Pressure Stall Information unter /proc/pressure/memory liefert dafür die präziseste, direkt interpretierbare Kennzahl, ergänzt durch anhaltende si/so-Aktivität in vmstat als Bestätigung.
Swappiness beeinflusst nur, welche Art von Speicher zuerst betroffen ist, löst aber kein Kapazitätsproblem selbst. Bei Datenbankservern ist die korrekte Dimensionierung von innodb_buffer_pool_size unter Berücksichtigung aller Nebendienste oft wichtiger als jede Swappiness-Anpassung. Wer PSI, vmstat und smaps kombiniert einsetzt, unterscheidet zuverlässig zwischen normalem, effizientem Speicherverhalten und einem tatsächlichen Engpass, der eine Kapazitätserweiterung rechtfertigt.
Swap-Nutzung trotz freiem RAM: Das Wichtigste auf einen Blick
Grundverhalten
Der Kernel lagert selten genutzte Seiten proaktiv aus, um Page-Cache und aktive Daten zu priorisieren.
Wichtigste Kennzahl
PSI full avg10 aus /proc/pressure/memory zeigt direkt, ob Prozesse tatsächlich ausgebremst werden.
Swappiness-Rolle
Steuert nur die Priorität zwischen Page-Cache und Anwendungsspeicher, löst kein Kapazitätsproblem.
MySQL-Sonderfall
innodb_buffer_pool_size korrekt dimensionieren statt Swappiness als Sofortlösung zu betrachten.