Was bedeutet Windows' Speicherauslastung eigentlich? — Working Set, Private Bytes, Commit und die Auslagerungsdatei richtig lesen
· Aktualisiert am: · Go Komura · Windows, Windows-Entwicklung, Speicherverwaltung, Working Set, Private Bytes, Commit, Auslagerungsdatei, Leistungsüberwachung, Fehlersuche, Sysinternals
Änderungsverlauf (Erstfassung, veröffentlicht am 4. Aug 2026)
- Erstveröffentlichung
Diesen Artikel zitieren(DOI (registriertes Archiv): 10.5281/zenodo.22175958)
Die folgenden DOIs verweisen auf bereits archivierte Versionen, die vom aktuellen Text abweichen können. Verwenden Sie die URL dieser Seite, um auf den aktuellen Text zu verweisen.
Go Komura (2026). Was bedeutet Windows' Speicherauslastung eigentlich? — Working Set, Private Bytes, Commit und die Auslagerungsdatei richtig lesen. KomuraSoft LLC. https://comcomponent.com/de/blog/windows-memory-usage-working-set-commit/
- DOI (registriertes Archiv)
- 10.5281/zenodo.22175958
- DOI (zuletzt registrierte Version)
- 10.5281/zenodo.22175959
Im Task-Manager zeigt der Speicher eines Prozesses 1,2GB an. Process Explorer zeigt jedoch ein Working Set von 1,5GB und Private Bytes von 2,4GB, und VMMap weist unter Size einen noch größeren Wert aus. Betrachtet man das gesamte System, steht dort Committed 19,6/31,8GB.
Wie viele Gigabyte Speicher verbraucht diese Anwendung nun also tatsächlich?
Allein daraus, dass diese Zahlen voneinander abweichen, folgt nicht, dass eine von ihnen falsch ist. Welche Kennzahl Sie betrachten sollten, hängt davon ab, was Sie wissen wollen.
Die derzeit im RAM liegende Menge, die diesem Prozess spezifisch zugewiesene Menge, die Menge, die das System auch künftig zu stützen verspricht, und der reservierte Bereich virtueller Adressen sind jeweils etwas anderes. Bevor Sie fragen, wie viele GB, klären Sie, die Menge wovon.
Was Windows-Speicherkennzahlen schwer verständlich macht, ist, dass sie alle unter demselben Wort Speicher angezeigt werden, obwohl sie tatsächlich die folgenden getrennten Achsen messen.
- Wie viel Adressraum genutzt wird
- Wie viel Commit verbraucht wurde
- Ob etwas derzeit im physischen RAM resident ist
- Ob die Seite prozessspezifisch oder gemeinsam nutzbar ist
- Wie viel Zuweisung das System insgesamt noch stützen kann
Dieser Artikel richtet sich an alle, die unter Windows 10/11 und aktuellem Windows Server wachsenden App-Speicherverbrauch oder systemweite Speicherengpässe untersuchen, und verbindet Working Set, Private Working Set, Private Bytes, Commit, Virtual Bytes, die Auslagerungsdatei, Available und Page Faults zu einem Gesamtbild.
Das Vorgehen zur Ursachensuche, warum .NET-Objekte nicht eingesammelt werden, wird ausführlich in GC-Wartezeit von einem Speicherleck in .NET unterscheiden behandelt, die konkrete Bedienung von VMMap und Process Explorer in Process Explorer / Handle / VMMap in der Praxis. Dieser Artikel konzentriert sich auf die dafür nötige Voraussetzung: das Lesen der Zahlen auf Seiten des Windows-Betriebssystems.
1. Das Wichtigste zuerst
Working Set ist die Menge, die gerade im RAM liegt, Private Bytes ist die diesem Prozess spezifisch versprochene Menge, und System Commit ist die vom gesamten System versprochene Menge. Lesen Sie zunächst diese drei getrennt.
Die Kennzahlen an die Frage anbinden, die sie beantworten
| Was Sie wissen wollen | Zu betrachtende Kennzahl | Vorsicht beim Lesen |
|---|---|---|
| Wie viel des Zielprozesses liegt jetzt im RAM | Working Set | Enthält nicht nur prozessspezifische Seiten, sondern auch gemeinsam nutzbare Seiten wie DLL-Code oder speicherabgebildete Dateien1 |
| Davon: wie viel RAM nutzt nur dieser Prozess | Private Working Set | Eine Näherung für das RAM, das dieser Prozess gerade allein belegt, nicht die gesamte von der App zugewiesene Menge2 |
| Wie groß ist das Commit, das dem Zielprozess eigen ist | Private Bytes | Unabhängig davon, ob die Seiten im RAM resident sind. Auch nicht die tatsächlich in die Auslagerungsdatei geschriebenen Bytes2 |
| Ob das systemweite Commit noch Spielraum hat | Committed X/Y | X ist die aktuelle Menge, Y die Obergrenze. X ist keine Nutzung der Auslagerungsdatei, und Y ergibt sich grob aus RAM plus Auslagerungsdatei3 |
Achten Sie auch auf den Win32-API-Namen PagefileUsage. Unter aktuellem Windows steht er praktisch für dieselbe Commit Charge wie Private Bytes, nicht für die tatsächlich in die Auslagerungsdatei geschriebene Menge.2
Nicht allein aus zugewiesen oder gewachsen urteilen
Wurde ein virtueller Adressbereich nur reserviert (Reserve), ist er lediglich für eine künftige Nutzung vorgemerkt. Er verbraucht weder RAM noch Commit-Obergrenze in gleicher Höhe; Reserve und Commit sind getrennte Stufen.45
Außerdem ist ein Page Fault nicht zwangsläufig Datenträger-E/A. Unterscheiden Sie Soft Faults, die sich innerhalb des RAM auflösen lassen, von Hard Faults, die aus der Auslagerungsdatei, einer ausführbaren Datei, einer speicherabgebildeten Datei oder Ähnlichem lesen.16
Auch ein Speicherleck lässt sich nicht anhand eines einzelnen großen Werts beurteilen. Prüfen Sie, ob Private Bytes oder deren Aufschlüsselung nach wiederholter gleicher Last nach jedem Durchlauf stufenweise weiter ansteigen, statt in denselben stationären Zustand zurückzukehren. Was Sie betrachten, ist nicht die Größe zu einem Zeitpunkt, sondern Untergrenze und Steigung nach der Wiederholung.
Nach Symptom oder Ziel lesen
| Was Sie gerade beschäftigt | Wo Sie lesen |
|---|---|
| Die Zahlen der Werkzeuge passen nicht zusammen, und Sie wissen nicht, welcher Sie trauen sollen | Kapitel 2: Die vier Achsen, die die Kennzahlen trennen, Kapitel 9: Bildschirme und Werkzeuge unterscheiden |
| OutOfMemory tritt auf, obwohl freier RAM verfügbar ist | 3.4: Zuweisungsgrenzen außerhalb des RAM, Kapitel 6: Die systemweite Commit-Obergrenze |
| Working Set oder Private Bytes wachsen weiter | Kapitel 4: Zu- und Abnahme der RAM-Residenz, Kapitel 5: Private Bytes und Freigabe |
| Sie überlegen, die Auslagerungsdatei zu verkleinern oder zu deaktivieren | 6.3: Rolle und Größe der Auslagerungsdatei |
| Die RAM-Auslastung ist hoch, aber kein großer Prozess ist zu sehen | Kapitel 7: Die Zusammensetzung des physischen RAM |
| Page Faults/sec ist hoch, und Sie wollen wissen, ob Speicher knapp ist | Kapitel 8: Der Unterschied zwischen Soft und Hard Faults |
| Sie wollen aus aufgezeichneten Zahlen die Ursache eingrenzen und ein Leck untersuchen | Kapitel 10: Kombinationen von Zahlen, Kapitel 11: Vorgehen bei der Leckuntersuchung |
Wenn Sie den Mechanismus von Grund auf lernen, lesen Sie der Reihe nach ab Kapitel 2; wenn Sie bereits Aufzeichnungen haben, beginnen Sie mit der Tabelle in Kapitel 10.
flowchart TB
accTitle: Die wichtigsten Windows-Speicherkennzahlen auswählen
accDescr: Die zu betrachtende Kennzahl ändert sich je nachdem, ob Sie RAM-Residenz, prozessprivates Commit, systemweites Commit oder den virtuellen Adressbereich wissen wollen
question["Was wollen Sie an der Speicherauslastung wissen?"]
question -->|Menge, die jetzt im RAM liegt| workingSet["Working Set"]
question -->|Dem Prozess spezifisch versprochene Menge| privateBytes["Private Bytes"]
question -->|Systemweit versprochene Menge| systemCommit["System Commit"]
question -->|Reservierter Adressbereich| virtualBytes["Virtual Bytes / Reserved"]
workingSet --> resident["Residenz im physischen RAM"]
privateBytes --> privateCommit["Prozessprivates Commit"]
systemCommit --> commitLimit["Mit dem Commit Limit vergleichen"]
virtualBytes --> addressSpace["Virtueller Adressraum"]
Abbildung 1: Zerlegen Sie die Beobachtung, dass viel Speicher genutzt wird, zuerst in vier Arten von Fragen.
In der Abbildung kennzeichnet eine durchgezogene Linie eine stets geltende Beziehung und eine gestrichelte Linie eine bedingte (die Bedingungen stehen bei jeder Beziehung auf der Detailseite). Die vollständige Liste der Beziehungen (18 insgesamt, mit Beleg und Sicherheitsgrad) und die Definitionen der wichtigsten Konzepte sind auf der Detailseite der Wissenskarte (auf Japanisch) zusammengestellt. Daten: JSON-LD / Turtle
2. Die Speicherauslastung in vier Achsen aufteilen
Die abweichenden Zahlen lassen sich ordnen, wenn Sie sie als dieselben Seiten, aus unterschiedlichen Blickwinkeln gezählt betrachten. Hier trennen wir vier Achsen: Zustand der Adresse, Hinterlegung der Daten, Residenz im RAM und gemeinsame Nutzbarkeit mit anderen Prozessen.
flowchart TB
accTitle: Vier unabhängige Achsen zur Einordnung einer Seite
accDescr: Zustand der virtuellen Adresse, Hinterlegung einer committeten Seite, Residenz im physischen RAM und gemeinsame Nutzbarkeit mit anderen Prozessen getrennt prüfen
page["Eine Seite entlang von vier Achsen"]
page --> address["Adresszustand"]
address --> addressValues["Free / Reserved / Committed"]
page --> backing["Hinterlegung"]
backing --> backingValues["Page-file-backed / File-backed"]
page --> residentAxis["RAM-Residenz"]
residentAxis --> residentValues["Resident / Not resident"]
page --> sharing["Gemeinsame Nutzbarkeit"]
sharing --> sharingValues["Private / Shareable"]
Abbildung 2: Auch bei einer einzelnen Seite werden Adresszustand, Hinterlegung, Residenz und gemeinsame Nutzbarkeit getrennt festgelegt.
Zustand, Hinterlegung und gemeinsame Nutzbarkeit nicht vermischen
Mapped ist kein Adresszustand neben Free, Reserved und Committed, sondern eine Art von Bereich. Seiten einer gemappten View können ebenfalls Committed sein.
Private ist andererseits kein Hinterlegungsmedium, sondern eine Klassifikation der gemeinsamen Nutzbarkeit. Lesen Sie die Hinterlegung als page-file-backed oder file-backed und die gemeinsame Nutzbarkeit als Private oder Shareable, jeweils getrennt.
Vergleichen, welche Kennzahl eine Seite zählt
Kombiniert man diese vier Achsen, sehen die Beziehungen der wichtigsten Kennzahlen so aus.
| Zustand der Seite | Working Set | Private Working Set | Private Bytes | Virtual-Bytes-Familie |
|---|---|---|---|---|
| Prozessspezifisch, committet, im RAM resident | Enthalten | Enthalten | Enthalten | Enthalten |
| Prozessspezifisch, committet, nicht im RAM resident | Nicht enthalten | Nicht enthalten | Enthalten | Enthalten |
| Gemeinsame Seite einer DLL oder gemappten Datei, im RAM resident | Enthalten | In der Regel nicht enthalten | In der Regel nicht enthalten | Enthalten |
| Reserviert, aber nicht committet | Nicht enthalten | Nicht enthalten | Nicht enthalten | Kann enthalten sein |
| Ungenutzter Adressbereich | Nicht enthalten | Nicht enthalten | Nicht enthalten | Normalerweise nicht enthalten |
flowchart TB
accTitle: Zuordnung von Seitenarten zu den wichtigsten Speicherkennzahlen
accDescr: Zeigt, welche Kennzahlen private residente Seiten, private nicht residente Seiten, gemeinsame residente Seiten und nur reservierte Bereiche enthalten
privateResident["Private, committet, im RAM resident"]
privateNonresident["Private, committet, nicht im RAM resident"]
sharedResident["Gemeinsame Seite, im RAM resident"]
reservedOnly["Reserved, nicht committet"]
workingSet["Working Set"]
privateWorkingSet["Private Working Set"]
privateBytes["Private Bytes"]
virtualBytes["Virtual-Bytes-Familie"]
privateResident --> workingSet
privateResident --> privateWorkingSet
privateResident --> privateBytes
privateResident --> virtualBytes
privateNonresident --> privateBytes
privateNonresident --> virtualBytes
sharedResident --> workingSet
sharedResident --> virtualBytes
reservedOnly --> virtualBytes
Abbildung 3: Working Set und Private Bytes zählen unterschiedliche Seitenmengen, daher gibt es keine einfache Inklusionsbeziehung.
Zwischen Working Set und Private Bytes gibt es keine feste Größenordnung
Wichtig ist hier, dass Working Set und Private Bytes in keiner einfachen Inklusionsbeziehung stehen.
Private Bytes enthalten Seiten, die dem Prozess eigen, derzeit aber nicht im RAM resident sind. Das Working Set enthält andererseits gemeinsame Seiten wie DLL-Code und Shared Memory, die Private Bytes nicht zählen. Je nach Prozess und Zeitpunkt kann das Working Set daher größer sein als Private Bytes, und umgekehrt.
Außerdem kann die bloße Summe der Working Sets mehrerer Prozesse dieselbe physische Seite, etwa eine gemeinsame DLL, mehrfach zählen. Die Aussage, die Summe der Working Sets aller Prozesse gleiche dem verwendeten RAM, gilt daher nicht unbedingt.
3. Virtueller Adressraum — Reserve und Commit sind unterschiedliche Dinge
Eine Adresse reservieren, committen und eine Seite zum ersten Mal berühren, sodass sie ins RAM gelangt, sind getrennte Ereignisse. Dieses Kapitel erklärt diese Unterschiede und davon ausgehend, warum eine Zuweisung auch bei freiem RAM fehlschlagen kann.
3.1. Eine virtuelle Adresse ist keine physische RAM-Adresse
Jeder Prozess hat einen eigenen virtuellen Adressraum. Die Zeiger, mit denen eine App arbeitet, zeigen nicht direkt auf eine Stelle im physischen RAM; Windows ordnet virtuelle Adressen über Seitentabellen physischen Seiten oder Daten in einer Datei zu.7
Deshalb kann der virtuelle Adressraum, der einem bestimmten 32-Bit-Prozess zur Verfügung steht, selbst auf einem PC mit 64GB RAM normalerweise weit kleiner sein. Umgekehrt ist ein 64-Bit-Prozess mit einem virtuellen Adressraum, der größer ist als der physische RAM, ganz gewöhnlich.
3.2. Reserved bedeutet nur, dass die Adresse vorgemerkt ist
VirtualAlloc mit MEM_RESERVE sichert einen zusammenhängenden Bereich virtueller Adressen für die künftige Nutzung. In diesem Stadium ist den Seiten kein physischer Speicher zugeordnet, und der Bereich lässt sich weder lesen noch schreiben.45
Auch wenn eine Datenbank oder Laufzeitumgebung etwa 8GB Adressraum für künftiges Wachstum reserviert hat, bedeutet das für sich genommen nicht, dass 8GB RAM oder 8GB Private Bytes verbraucht wurden.
3.3. Committed ist das Versprechen, bei Bedarf zu stützen
MEM_COMMIT versetzt die virtuellen Seiten in den Zustand Committed; Windows verspricht, die nötige Hinterlegung bereitzustellen. Im Moment des Commit wird der Betrag der Commit Charge des Systems zugerechnet.5
Committed heißt nicht zwangsläufig les- oder schreibbar
Die Erlaubnis zum Lesen, Schreiben und Ausführen wird getrennt über den Seitenschutz festgelegt, etwa PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE und PAGE_NOACCESS. Committed zu sein bedeutet für sich genommen nicht les- und schreibbar.5
Commit und Residenz im RAM sind ebenfalls getrennte Stufen
Die tatsächliche physische Seite wird unter Umständen erst beim ersten Zugriff zugewiesen. Eine erstmals berührte Seite wird mit Nullen initialisiert und gelangt über einen Demand-zero Fault ins Working Set.51
Dasselbe Wort zugewiesen umfasst daher die folgenden drei Stufen.
flowchart TB
accTitle: Die drei Stufen von Reserve über Commit bis zur RAM-Residenz
accDescr: Zeigt den Ablauf, in dem ein virtueller Adressbereich reserviert, die Seite committet und beim ersten Zugriff eine physische Seite zugewiesen und ins Working Set aufgenommen wird
reserve["MEM_RESERVE: Adressbereich sichern"]
reserve -.-> virtualMetric["Schlägt sich in der Virtual-Bytes-Familie nieder"]
reserve -->|MEM_COMMIT| committed["Committed: je nach Seitenschutz zugreifbar"]
committed -.-> commitMetric["Schlägt sich in Private Bytes / System Commit nieder"]
committed -->|Erster Zugriff, Demand-zero Fault| resident["Physische Seite zugewiesen, im RAM resident"]
resident -.-> workingSetMetric["Schlägt sich im Working Set nieder"]
committed -.->|Falls nie zugegriffen| nonresident["Committed, aber nicht resident"]
Abbildung 4: Reserve, Commit und der erste Zugriff sind getrennte Ereignisse und bewegen jeweils eine andere Kennzahl.
Diese drei Stufen bewegen die Zahlen der Virtual-Bytes-Familie, der Private Bytes und des Working Set unabhängig voneinander.
3.4. Warum OutOfMemory auch bei freiem RAM auftreten kann
Ob eine Speicherzuweisung gelingt, entscheidet sich nicht allein am freien RAM.
- Der virtuelle Adressraum des Prozesses ist aufgebraucht
- Es gibt keinen zusammenhängenden freien Adressbereich der benötigten Größe
- Die systemweite Commit Charge hat das Commit Limit erreicht
- Ein Job Object, ein Container, die Laufzeitumgebung oder eine Bibliothek setzt eine eigene Obergrenze
- Der Prozess ist 32-Bit
- Der native Heap ist fragmentiert
Auch unter 64-Bit-Windows beträgt der virtuelle Adressraum eines 32-Bit-Prozesses im Benutzermodus normalerweise 2GB, wenn IMAGE_FILE_LARGE_ADDRESS_AWARE nicht gesetzt ist. Eine 32-Bit-App mit diesem Flag kann unter 64-Bit-Windows bis zu 4GB nutzen.8
Deshalb ist es kein Widerspruch, wenn der PC 20GB freien RAM hat und die 32-Bit-App dennoch bei etwa 1,6GB scheitert. Es ist kein RAM-Problem; der Prozess stößt vermutlich an Fragmentierung oder an die Obergrenze des Adressraums.
4. Working Set — die Seiten, die gerade im RAM liegen
Das Working Set ist die Menge der Seiten im virtuellen Adressraum des Prozesses, die derzeit im physischen RAM resident sind.1
Darin mischen sich unter anderem:
- Heaps und Stacks, die dem Prozess eigen sind
- Code und schreibgeschützte Daten von EXE und DLLs
- speicherabgebildete Dateien
- Shared Memory
- Seiten, die nach Copy-on-write diesem Prozess eigen geworden sind
- Seiten, die die Laufzeitumgebung und verschiedene Bibliotheken berührt haben
4.1. Ein wachsendes Working Set bedeutet nicht zwangsläufig eine größere Zuweisung
Wenn es wächst, können bestehende Seiten lediglich ins RAM gelangt sein
Werden bereits committete Seiten zum ersten Mal zugegriffen, kann das Working Set allein wachsen, während Private Bytes unverändert bleibt.
Ebenso können beim sequenziellen Lesen einer großen, speicherabgebildeten Datei dateibasierte Seiten ins Working Set gelangen, während Private Bytes kaum wächst.
Wenn es schrumpft, kann derselbe Speicher weiterhin gehalten werden
Trimt Windows das Working Set unter Speicherdruck, schrumpft nur das Working Set, während die App denselben Speicher logisch weiterhin hält. Werden die Seiten später erneut berührt, kehren sie über Page Faults zurück.
Mit anderen Worten: Ein Anstieg des Working Set bedeutet nicht zwangsläufig neu zugewiesen, und ein Rückgang nicht zwangsläufig freigegeben. Lesen Sie Änderungen der Residenz getrennt von Zuweisung und Freigabe.
flowchart TB
accTitle: Typischer Ablauf, in dem nur das Working Set steigt und fällt
accDescr: Dieselbe committete Seite gelangt beim ersten Zugriff ins RAM, wird durch Trim nicht resident und kehrt beim erneuten Zugriff zurück, während Private Bytes durchgängig angerechnet bleibt
committed["Dieselbe committete Seite"]
committed -->|Erster Zugriff| resident["Im RAM resident"]
resident -->|Trim unter Speicherdruck| nonresident["Nicht resident"]
nonresident -->|Page Fault beim erneuten Zugriff| resident
resident -.-> inWorkingSet["Im Working Set enthalten"]
nonresident -.-> outsideWorkingSet["Nicht im Working Set enthalten"]
committed -.-> privateBytes["Solange committet, in Private Bytes angerechnet"]
Abbildung 5: Das Working Set steigt und fällt mit der Residenz, aber solange das Commit derselben Seite bestehen bleibt, sinken Private Bytes nicht.
4.2. Das Working Set enthält auch gemeinsame Seiten
Teilen zehn Prozesse die Codeseiten derselben DLL, können diese Seiten im Working Set jedes Prozesses erscheinen, obwohl im physischen RAM nur eine Kopie existiert. Dass die Summe der Working Sets den eingebauten RAM übersteigt, ist daher nicht sofort ungewöhnlich.
Wollen Sie näher an das RAM herankommen, das dieser Prozess gerade allein belegt, betrachten Sie das Private Working Set. Auch das ist jedoch nicht der gesamte vom Prozess zugewiesene Speicher, sondern nur die derzeit residenten privaten Seiten.
4.3. Das erzwungene Verkleinern des Working Set behebt kein Leck
Mit EmptyWorkingSet oder SetProcessWorkingSetSize lassen sich Seiten aus dem Working Set eines Prozesses verdrängen. Das ist jedoch keine Operation, die Commit oder Verweise auf dem Heap freigibt. Nur die scheinbare RAM-Nutzung sinkt, während Private Bytes unverändert bleibt, und beim nächsten Zugriff können Page Faults zunehmen.9
Sinkt die Zahl im Task-Manager nur unmittelbar nach einem Knopf zum Reduzieren des Speichers und kehrt zurück, sobald Sie weiterarbeiten, wurde möglicherweise nur das Working Set getrimmt, nicht freigegeben.
5. Private Bytes — die einem Prozess eigene Commit-Menge
Private Bytes ist die Menge virtuellen Speichers, die ausschließlich für diesen Prozess committet wurde. Sie steht für die Commit Charge, die sich nicht mit einem anderen Prozess teilen lässt, unabhängig davon, ob sie derzeit im RAM resident ist. In Microsofts PROCESS_MEMORY_COUNTERS_EX entspricht PrivateUsage diesem Wert.102
Die Win32-API hat außerdem das irreführend benannte Feld PagefileUsage, doch die aktuelle Dokumentation definiert es als die Commit Charge dieses Prozesses und erklärt, dass es denselben Wert hat wie PrivateUsage. Mit anderen Worten: 2GB Private Bytes bedeuten nicht, dass 2GB nach pagefile.sys geschrieben wurden.2
Private Bytes werden typischerweise von Folgendem beeinflusst.
- Commit nativer Heaps, die
HeapAlloc,malloc,newund Ähnliches nutzen - Private Data, die direkt mit
VirtualAlloccommittet wurde - Der committete Bereich des .NET-GC-Heaps
- Der tatsächlich committete Teil jedes Thread-Stacks
- Die Commit Charge für die gesamte View, die beim Mappen einer Copy-on-write-View (
FILE_MAP_COPY) beansprucht wird - Private Puffer, die Bibliotheken und Geräte-SDKs intern halten
Beachten Sie außerdem, dass bei Copy-on-write die Anrechnung vor dem tatsächlichen Schreiben erfolgt. Weil jede Seite einer mit FILE_MAP_COPY erzeugten View künftig privat werden kann, wird die Commit Charge bereits beim Mappen beansprucht, damit die gesamte View über die Auslagerungsdatei hinterlegt werden kann.11
Deshalb können System Commit und die Commit Charge des Prozesses (Private Bytes) um die volle Größe der View wachsen, noch bevor etwas geschrieben und eine private Kopie erzeugt wurde.11
5.1. Warum Private Bytes auch nach free oder einer GC nicht sinkt
Freigabe innerhalb der App von der Rückgabe an das Betriebssystem trennen
Selbst wenn Speicher aus Sicht der Anwendung freigegeben wird, kann die Laufzeitumgebung oder der Heap-Allokator den Bereich für künftige Wiederverwendung behalten, statt ihn an das Betriebssystem zu decommitten. Dann ist der Speicher innerhalb der App wiederverwendbar, Private Bytes bleiben aber hoch.
Private Bytes bleiben auch hoch, wenn nur ein Teil eines großen Bereichs überlebt, der Heap fragmentiert ist oder Caches und Pools bis an ihre Obergrenze aufgewärmt sind.
Die Änderung nach derselben Last vergleichen, nicht den hohen Plateauwert
Hohe Private Bytes allein beweisen kein Leck. Vergleichen Sie über die Zeit in dieser Reihenfolge.
- Wiederholen Sie dieselbe Verarbeitung dieselbe Anzahl von Malen.
- Lassen Sie nach jedem Durchlauf dieselbe Wartezeit verstreichen.
- Prüfen Sie, ob Private Bytes auf dasselbe Niveau zurückkehrt oder sich bei einem festen Wert einpendelt.
- Prüfen Sie mit VMMap oder einem Heap-Dump, welcher Bereich oder Typ gewachsen ist.
flowchart TB
accTitle: Warum Private Bytes nach free oder einer GC nicht sinkt
accDescr: Private Bytes ändert sich unterschiedlich, je nachdem, ob der Allokator einen von der App nicht mehr benötigten Bereich an das Betriebssystem zurückgibt oder zur Wiederverwendung behält
release["Die App macht Speicher über free / GC entbehrlich"]
release --> decision{"Gibt der Allokator ihn an das OS zurück?"}
decision -->|Decommit / Release| returned["Die Commit Charge sinkt"]
returned --> lower["Private Bytes sinkt"]
decision -->|Zur Wiederverwendung behalten| retained["Der Bereich bleibt committet"]
retained --> high["Private Bytes bleibt hoch"]
retained --> reasons["Pools, Caches, Fragmentierung"]
Abbildung 6: Innerhalb der App wiederverwendbar zu werden ist nicht dasselbe, wie Commit an das Betriebssystem zurückzugeben.
5.2. Die Form, die stark auf ein Leck hindeutet
Ein treppenartiger Anstieg wie der folgende, bei dem die Untergrenze mit jeder Last steigt, verdient Aufmerksamkeit.
Private Bytes
^
| ________
| ______|
| ______|
|_____|
+----------------------------> Wiederholungen derselben Verarbeitung
Allerdings kann auch eine Treppe nur in den ersten Durchläufen steigen, durch anfängliches JIT, Schriftarten, Bilddecoder, Verbindungspools oder das Aufwärmen von Caches, und sich danach stabilisieren. Entscheidend ist nicht dass sie wächst, sondern dass sie nicht in einen stationären Zustand konvergiert.
6. System Commit — was Committed X/Y tatsächlich ist
Bisher haben wir vor allem Kennzahlen eines einzelnen Prozesses betrachtet. Committed X/Y unter Leistung, Speicher im Task-Manager ist eine systemweite Kennzahl. Lesen Sie sie getrennt von den Werten einzelner Prozesse.
- X: System Commit Charge
Der committete Speicher, den Windows derzeit systemweit zu stützen verspricht - Y: System Commit Limit
Die Obergrenze der Commit-Menge, die das System stützen kann
Das Commit Limit ergibt sich grob aus physischem RAM plus allen Auslagerungsdateien. Ohne Auslagerungsdatei liegt es etwas unter dem eingebauten RAM.36
flowchart TB
accTitle: Das Verhältnis von System Commit Charge und Commit Limit
accDescr: Prozessprivates, Shared-Section- und Kernel-Commit bilden den aktuellen Wert X, physischer RAM und die Auslagerungsdatei stützen die Obergrenze Y
processCommit["Private Commit jedes Prozesses"] --> charge["System Commit Charge: X"]
sharedCommit["Commit von über die Auslagerungsdatei hinterlegten Shared Sections"] --> charge
kernelCommit["Commit des Kernels"] --> charge
physicalRam["Physischer RAM"] --> limit["System Commit Limit: Y"]
pageFiles["Auslagerungsdateien"] --> limit
charge -->|X kann Y nicht überschreiten| limit
Abbildung 7: X ist die derzeit versprochene Menge, Y die Obergrenze, die dieses Versprechen stützen kann, keine Anzeige der Nutzung der Auslagerungsdatei.
Die System Commit Charge umfasst nicht nur die Summe der Private Bytes aller Prozesse, sondern auch das Commit von Shared Sections, die über die Auslagerungsdatei hinterlegt werden, und das vom Kernel verbrauchte Commit. Die Summe der prozessbezogenen Private Bytes erklärt X daher nicht vollständig.
6.1. Commit Charge ist keine Nutzung der Auslagerungsdatei
Die 20GB in 20/31GB sind keine Menge auf dem Datenträger
Betrachten Sie ein System mit 16GB RAM, 16GB Auslagerungsdatei und Committed 20/31GB.
Diese 20GB bedeuten nicht, dass 20GB in die Auslagerungsdatei geschrieben wurden. Die 20GB sind die Gesamtmenge, für die Windows versprochen hat, bei Bedarf Hinterlegung in RAM, Auslagerungsdatei oder Ähnlichem bereitzustellen, etwa für private, änderbare Seiten.
In diesen 20GB mischen sich folgende Zustände.
- Der Großteil ist im RAM resident
- Ein Teil wurde in die Auslagerungsdatei ausgelagert
- Ein Teil ist committet, aber noch nicht zum ersten Mal zugegriffen
- Ein Teil wird als Commit auf der Kernel-Seite verbraucht
Die Nutzung der Auslagerungsdatei an einem anderen Zähler ablesen
Wollen Sie die tatsächliche Auslastung der Auslagerungsdatei sehen, prüfen Sie Paging File(*)\% Usage getrennt vom Commit. Auch Microsofts Unterlagen erklären jedoch, dass eine hohe Nutzung der Auslagerungsdatei allein noch kein Leistungsproblem bedeutet und zusammen mit dem Erreichen des Commit Limit, der Modified Page List und der tatsächlichen Paging-E/A beurteilt werden sollte.6
6.2. Was passiert, wenn sich das System dem Commit Limit nähert
Erreicht die System Commit Charge das Commit Limit, lassen sich neue Commit-Anforderungen nicht mehr stützen. Das führt zu fehlgeschlagenen Speicherzuweisungen in Prozessen, Abstürzen von Apps und einem nicht mehr bedienbaren System.3
Hier zählt das X/Y des Commit mehr als freier RAM. Selbst wenn Sie Working Sets trimmen, um freien RAM zu schaffen, löst das das Erreichen des Commit Limit nicht, solange die Commit Charge selbst nicht sinkt.
6.3. Die drei Aufgaben der Auslagerungsdatei
Die Auslagerungsdatei hat vor allem die folgenden Aufgaben.
- Das Commit Limit erweitern
- Wenig genutzte geänderte Seiten aus dem RAM auslagern können
- Je nach Konfiguration Systemabsturzabbilder stützen
Deaktivieren oder Größenänderung anhand von Spitzen-Commit und Dump-Anforderungen entscheiden
Die Auslagerungsdatei zu deaktivieren ist kein einfacher Zusammenhang der Art, dass Datenträger-E/A immer abnimmt und es deshalb schneller wird. Im Gegenteil senkt sie das Commit Limit, lässt geänderte Seiten, die vorerst nicht gebraucht werden, eher im RAM, und kann es unmöglich machen, beim Absturz das benötigte Abbild zu erzeugen.36
Die angemessene Größe der Auslagerungsdatei ergibt sich nicht allein aus dem eingebauten RAM. Auch Microsoft erklärt, dass sie sich nicht verallgemeinern lässt, weil die Spitzen-System-Commit-Charge und die Art des benötigten Absturzabbilds von System zu System unterschiedlich sind.6
7. Die Zusammensetzung des physischen RAM — nicht allein an niedrigem Available urteilen
Physischer RAM wird nicht nur für die Working Sets von Benutzerprozessen verwendet.
- Das Working Set jedes Prozesses
- Der Systemdateicache
- Seitenlisten wie Standby, Modified, Free und Zeroed
- Paged Pool und Nonpaged Pool des Kernels
- Speicher, den Gerätetreiber halten
- Der Store der Speicherkompression
- Bereiche, die mit GPU und Geräten geteilt oder für sie reserviert sind
- Hardware-Reservierungen
7.1. Available umfasst auch wiederverwendbaren Cache
Free und Available bedeuten nicht dasselbe. Windows’ Available MBytes enthält neben Free und Zeroed auch Standby-Seiten, die bei Bedarf wiederverwendet werden können. Es ist keine Kennzahl, die nur vollständig ungenutzten RAM zählt.12
- Free: Seiten, die derzeit keinem Zweck zugeordnet sind
- Zeroed: Seiten, die bereits genullt sind, damit sie sicher an einen anderen Prozess übergeben werden können
- Standby: Seiten, die aus einem Working Set entfernt wurden, deren Inhalt aber noch im RAM zwischengespeichert ist
- Modified: Seiten, deren Inhalt geändert wurde und die vor der Wiederverwendung in die passende Hinterlegung zurückgeschrieben werden müssen
flowchart TB
accTitle: Bewegung zwischen Working Set und Seitenlisten
accDescr: Zeigt den Ablauf, in dem eine genutzte Seite unverändert nach Standby oder geändert nach Modified wandert und dann über erneuten Zugriff, Zurückschreiben und Wiederverwendung läuft
workingSet["Working Set: in Verwendung"]
workingSet -->|Unveränderte Seite entfernen| standby["Standby: Wiederverwendungskandidat, der den Inhalt behält"]
workingSet -->|Geänderte Seite entfernen| modified["Modified: wartet auf Zurückschreiben"]
modified -->|Zurückschreiben abgeschlossen| standby
standby -->|Erneuter Zugriff| workingSet
standby -->|Für einen anderen Zweck wiederverwendet| reused["Anderem Zweck zugeordnet"]
free["Free: ungenutzt"] -->|Nullen| zeroed["Zeroed: bereit für neue Zuweisung"]
zeroed -->|Zugriff nach der Zuweisung| workingSet
standby -.-> available["In Available enthalten"]
free -.-> available
zeroed -.-> available
Abbildung 8: Available enthält nicht nur vollständig freie Seiten, sondern auch Standby-Seiten, die bei Bedarf wiederverwendet werden können.
Wenig Free von physischem Speicherdruck trennen
Den gesamten Cache wegzuwerfen, um freien RAM zu vermehren, ist nicht immer ein Gewinn. Liegen die benötigten Daten noch auf Standby, lassen sie sich beim erneuten Zugriff schnell ins Working Set zurückholen, ohne vom Datenträger zu lesen.
Selbst wenn der Task-Manager wenig Free anzeigt, kann Windows den RAM also lediglich als Cache sinnvoll nutzen, solange Available ausreicht und Hard Page Faults sowie Datenträgerwartezeiten kein Problem sind.
7.2. Wenn RAM ohne große Prozesse schrumpft
Speicherverbrauch, der sich nicht durch die Summe der Private Working Sets aller Prozesse erklären lässt, ist nicht ungewöhnlich.
- Dateicache und speicherabgebildete Dateien
- Nonpaged Pool / Paged Pool
- Von Treibern gesperrte Seiten
- Gemeinsame Seiten
- Speicherkompression
- Zuweisungen im Zusammenhang mit Virtualisierung oder GPU
In diesem Fall ist es sinnvoller, in Sysinternals RAMMap Use Counts, Processes, Priority Summary und File Summary zu prüfen, als weiter die Prozessliste zu betrachten. RAMMap ist das offizielle Werkzeug, um physischen Speicher nach Verwendungszweck, Seitenliste und Datei zu zerlegen.13
Wächst nur der Nonpaged Pool weiter, sind Sie an dem Punkt, ein Leck in einem Treiber oder auf der Kernel-Seite zu vermuten, nicht in den Private Bytes einer Benutzeranwendung.
8. Page Fault — ein hoher Wert allein ist keine Anomalie
Ein Page Fault entsteht, wenn ein Prozess auf eine Seite zugreift, die derzeit nicht in seinem Working Set liegt. Trotz des Wortes Fault im Namen ist das keine außergewöhnliche Störung, sondern der normale Mechanismus, der virtuellen Speicher bewegt.1
Zuerst ist zu trennen, ob vom Datenträger gelesen werden muss. Darüber hinaus betrachten Sie nicht nur die Anzahl der Ereignisse, sondern auch die tatsächliche Wartezeit und die Verschlechterung der Reaktion.
8.1. Soft Page Faults
Diese lassen sich auflösen, ohne vom Datenträger zu lesen.
- Die Seite liegt noch auf Standby oder in Transition
- Dieselbe gemeinsame Seite liegt im Working Set eines anderen Prozesses
- Auf eine committete Seite wird zum ersten Mal zugegriffen, und eine Nullseite wird zugewiesen
- Das Read-ahead des Speichermanagers hat sie bereits ins RAM geholt
Deshalb bedeutet ein hoher Wert von \Memory\Page Faults/sec nicht zwangsläufig, dass Datenträger-E/A oder Verzögerung auftritt.
8.2. Hard Page Faults
Diese erfordern, den Inhalt aus einem Hinterlegungsspeicher auf dem Datenträger zu lesen. Die Quelle ist nicht auf die Auslagerungsdatei beschränkt.
- Code und Daten von
.exeund.dll - speicherabgebildete Dateien
- die Auslagerungsdatei
flowchart TB
accTitle: Die Verzweigung zwischen Soft Page Fault und Hard Page Fault
accDescr: Beim Zugriff auf eine Seite, die nicht im Working Set liegt, wird ohne Speicher-E/A ein Soft Page Fault, mit Speicher-E/A ein Hard Page Fault verarbeitet
access["Zugriff auf eine Seite, die nicht im Working Set liegt"] --> storageIo{"Ist Speicher-E/A nötig?"}
storageIo -->|Nein: Standby, gemeinsam, Demand-zero usw.| soft["Soft Page Fault"]
soft --> resident["Ins Working Set, ohne vom Datenträger zu lesen"]
storageIo -->|Ja| hard["Hard Page Fault"]
hard --> source{"Woher wird gelesen?"}
source --> image["EXE / DLL"]
source --> mapped["Speicherabgebildete Datei"]
source --> pagefile["Auslagerungsdatei"]
image --> loaded["Nach dem Laden ins Working Set"]
mapped --> loaded
pagefile --> loaded
Abbildung 9: Am Namen Page Fault allein lässt sich nicht entscheiden, ob Datenträger-E/A stattfand.
Microsoft nennt \Memory\Pages/sec, \Memory\Page Reads/sec, \Memory\Pages Input/sec und ähnliche als Zähler für Hard Faults. Weil hohe Werte nicht unbedingt knappen Speicher bedeuten, korrelieren Sie sie mit Available MBytes, Datenträgerlatenz und der tatsächlichen Antwortzeit.6
8.3. Keine pauschale Schwelle festlegen
Ein fester Wert wie Page Faults/sec über 1000 ist ungewöhnlich bedeutet je nach Speichergerät, Seitengröße, Arbeitslast und Zugriffslokalität etwas anderes.
In der Praxis legen Sie Folgendes auf dieselbe Zeitachse.
Memory\Available MBytesMemory\Pages Input/secMemory\Page Reads/sec- Read-Latenz und Warteschlange des betroffenen Datenträgers
- Working Set und Private Bytes des Zielprozesses
- Verarbeitungszeit, Timeouts und UI-Reaktion der App
Sinkt Available gleichzeitig mit steigender Last, steigen Pages Input/sec und Datenträgerwartezeiten, und verschlechtert sich auch die Verarbeitungszeit, haben Sie Gründe, Paging durch physischen Speicherdruck zu vermuten.
9. Welcher Bildschirm oder welches Werkzeug zeigt was
Wenn Sie zuerst festlegen, ob es um einen Prozess oder das gesamte System geht und ob Sie eine Momentaufnahme der Aufschlüsselung oder eine Zeitreihe brauchen, fällt die Wahl des Werkzeugs leichter. Ordnen Sie in der folgenden Tabelle Kennzahlen und Werkzeuge zu, und gehen Sie dann zur Aufzeichnung über.
| Was Sie wissen wollen | Zuerst zu betrachtende Kennzahl | Wichtige Werkzeuge |
|---|---|---|
| Wie viel der Zielprozess derzeit im RAM hält | Working Set | Task-Manager, Process Explorer, Get-Process |
| Davon der dem Prozess eigene RAM | Private Working Set / Working Set - Private | Detailspalten im Task-Manager, Process Explorer, PerfMon |
| Die dem Zielprozess eigene Commit-Menge | Private Bytes / Commit Size | Process Explorer, PerfMon, VMMap, Get-Process |
| Der virtuelle Adressbereich des Prozesses | Virtual Bytes / Size | Process Explorer, VMMap, Get-Process |
| Der systemweite Commit-Spielraum | Committed Bytes / Commit Limit | Task-Manager Leistung, PerfMon |
| Der Wiederverwendungsspielraum des physischen RAM | Available MBytes | Task-Manager, PerfMon |
| Aufschlüsselung von Standby, Modified und Dateicache | Seitenlisten und Aufschlüsselung nach Zweck | RAMMap |
| Was innerhalb der Private Bytes gewachsen ist | Heap / Private Data / Managed Heap usw. | VMMap, WinDbg, laufzeitspezifische Dumps |
| Paging mit Datenträgerbeteiligung | Pages Input/sec, Page Reads/sec, Datenträgerlatenz | PerfMon, WPR/WPA |
flowchart TB
accTitle: Werkzeuge für die Windows-Speicheruntersuchung auswählen
accDescr: Das Werkzeug richtet sich danach, ob das Ziel ein Prozess oder das gesamte System ist, ob ein Zeitpunkt oder eine Zeitreihe gebraucht wird und ob bis in die Laufzeitumgebung verfolgt werden soll
question["Was wollen Sie eingrenzen?"]
question --> processScope{"Betrifft es einen Prozess?"}
processScope -->|Ja| processTime{"Zeitpunkt oder Zeitreihe?"}
processTime -->|Aufschlüsselung zu einem Zeitpunkt| vmmap["VMMap"]
processTime -->|Zeitreihe| perfmon["PerfMon / PowerShell"]
processScope -->|Gesamtes System| systemView{"Physische RAM-Aufschlüsselung oder Zeitachse?"}
systemView -->|Physische RAM-Aufschlüsselung| rammap["RAMMap"]
systemView -->|Zeitachse einschließlich CPU, E/A und Warten| wpa["WPR / WPA"]
question --> runtime{"Bis zum Halten innerhalb der Laufzeit verfolgen?"}
runtime -->|.NET-Heap| dotnet["dotnet-dump / PerfView"]
runtime -->|Nativer Heap| native["WinDbg / Application Verifier"]
Abbildung 10: Legen Sie zuerst Zielbereich und Zeitachse fest, wählen Sie die nötigen Werkzeuge ohne Über- oder Unterausstattung.
9.1. Task-Manager
Im Task-Manager betrachten Sie die Bildschirme getrennt.
- Prozesse oder Details: Working-Set-Familie und Commit-Size-Familie einzelner Prozesse
- Leistung, Speicher: systemweites In use, Available, Committed, Cached, Paged pool, Non-paged pool
Urteilen Sie nicht allein am Spaltennamen Speicher. Klicken Sie in der Registerkarte Details mit der rechten Maustaste auf die Spaltenüberschriften und fügen Sie Working Set, Peak Working Set, Commit Size und andere benötigte Spalten hinzu. Die Spaltennamen unterscheiden sich je nach Windows-Version und Anzeigesprache etwas; prüfen Sie die Bedeutung der Spalte, bevor Sie aufzeichnen.
9.2. Eine Zeitreihe mit PowerShell erfassen
Zuerst drei Kennzahlen desselben Prozesses aufzeichnen
Kennt man die ID des Zielprozesses, lassen sich mit Get-Process die Verläufe von Working Set, Private Bytes und Virtual Bytes gleichzeitig erfassen.
param(
[Parameter(Mandatory)]
[int]$ProcessId,
[int]$IntervalSeconds = 5,
[int]$SampleCount = 60
)
$samples = for ($i = 0; $i -lt $SampleCount; $i++) {
$process = Get-Process -Id $ProcessId -ErrorAction Stop
[pscustomobject]@{
Timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
ProcessId = $process.Id
WorkingSetMB = [math]::Round($process.WorkingSet64 / 1MB, 1)
PrivateBytesMB = [math]::Round($process.PrivateMemorySize64 / 1MB, 1)
VirtualBytesMB = [math]::Round($process.VirtualMemorySize64 / 1MB, 1)
Handles = $process.HandleCount
Threads = $process.Threads.Count
}
Start-Sleep -Seconds $IntervalSeconds
}
$samples | Format-Table -AutoSize
$samples | Export-Csv .\memory-samples.csv -NoTypeInformation -Encoding utf8
.NETs Process.WorkingSet64 entspricht dem Working Set, PrivateMemorySize64 den Private Bytes und VirtualMemorySize64 den Virtual Bytes.141516
Verwechslungen durch mehrere Instanzen oder Neustarts vermeiden
Bei Apps mit mehreren Instanzen verfolgen Sie den Prozess über die PID, nicht über den Namen. Bei Langzeitüberwachung, in der sich die PID durch Neustarts ändert, müssen Startzeit, Dienstname und Ähnliches mit aufgezeichnet werden, damit das Ziel nicht verwechselt wird.
9.3. System und Prozess mit PerfMon auf dieselbe Zeitachse bringen
Mindestens die folgenden Zähler gleichzeitig aufzuzeichnen erleichtert die Eingrenzung.
\Process(<Ziel>)\ID Process
\Process(<Ziel>)\Working Set
\Process(<Ziel>)\Working Set - Private
\Process(<Ziel>)\Private Bytes
\Process(<Ziel>)\Virtual Bytes
\Memory\Available MBytes
\Memory\Committed Bytes
\Memory\Commit Limit
\Memory\Pages Input/sec
\Memory\Page Reads/sec
\Memory\Pool Nonpaged Bytes
\Memory\Pool Paged Bytes
Nicht nur den Instanznamen, sondern die PID jedes Samples prüfen
Gibt es mehrere Prozesse desselben Namens oder startet der überwachte Prozess neu, lässt sich das Ziel allein über Instanznamen wie Process(name) oder Process(name#N) nicht festhalten. Zeichnen Sie in jedem Sample auch ID Process auf und verwenden Sie nur Instanzen, deren Wert mit der verfolgten PID übereinstimmt. Überspannt die Überwachung einen Neustart, bei dem sich die PID ändert, zeichnen Sie auch den Zeitpunkt des Wechsels gesondert auf.
Wenn ein Zähler nicht gefunden wird, die Anzeigesprache prüfen
Die Namen der Windows-Leistungsindikatoren können je nach Anzeigesprache lokalisiert sein. Werden englische Namen in PowerShell nicht gefunden, fügen Sie sie über die PerfMon-Oberfläche hinzu oder prüfen Sie die Namen der lokalen Umgebung mit Get-Counter -ListSet *.
9.4. Die Rollen von VMMap und RAMMap nicht verwechseln
- VMMap: Zerlegt den virtuellen Speicher und das Working Set eines Prozesses in Heap, Image, Mapped File, Private Data, Managed Heap und Ähnliches
- RAMMap: Zerlegt den physischen RAM des gesamten Systems nach Verwendungszweck, Seitenliste, Prozess und Datei
Wodurch die Private Bytes dieses Prozesses gewachsen sind, beantwortet VMMap; wofür RAM verwendet wurde, der sich in der Prozessliste nicht erklärt, RAMMap.1713
10. Symptome aus Kombinationen von Zahlen lesen
Aufgezeichnete Werte liest man daran, welche Kennzahlen sich gemeinsam bewegen und welche unverändert bleiben. Die folgende Tabelle dient nicht dazu, die Ursache festzuschreiben, sondern dazu, die als Nächstes zu prüfende Aufschlüsselung und die Bedingungen auszuwählen.
| Beobachtete Form | Zuerst zu bedenken | Als Nächstes zu prüfen |
|---|---|---|
| Working Set wächst, Private Bytes bleibt stabil | Erstzugriff auf bestehende Seiten, gemeinsame DLLs, gemappte Dateien, Dateicache | Image / Mapped File in VMMap, Pages Input/sec |
| Private Bytes wächst, Working Set bleibt stabil | Privates Commit ist gewachsen, aber nicht resident oder getrimmt | Heap / Private Data / Managed Heap in VMMap |
| Beide wachsen direkt nach dem Start und flachen danach ab | JIT, Cache, Pool, Aufwärmen der Initialisierung | Ob sie bei zusätzlicher gleicher Last erneut wachsen |
| Die Untergrenze der Private Bytes steigt mit jeder Last | Leck, Cache ohne Obergrenze, Allokator, der nach der Freigabe behält | VMMap-Snapshots davor und danach, Heap-Dump |
| Nur das Working Set fällt abrupt und kehrt bei Bedienung zurück | Betriebssystem oder App hat das Working Set getrimmt | Private Bytes, Pages Input/sec, Antwortzeit |
| X in Committed X/Y nähert sich Y | Systemweiter Commit-Druck | Prozesse mit den höchsten Private Bytes, Paged/Nonpaged Pool, Einstellung der Auslagerungsdatei |
| Available ist niedrig, Pages Input/sec und Datenträgerlatenz sind hoch | Physischer RAM-Druck und Hard Paging | Prozesse mit dem höchsten Working Set, RAMMap, Korrelation mit der Arbeitslast |
| Die RAM-Auslastung ist hoch, aber es gibt keinen großen Prozess | Cache, gemeinsame Seiten, Kernel-Pools, Treiber, Kompression usw. | RAMMap, Pool Nonpaged/Paged Bytes |
| Freier RAM ist vorhanden, aber nur die 32-Bit-App scheitert | Obergrenze oder Fragmentierung des virtuellen Adressraums | Free/Reserved in VMMap, LAA-Einstellung der ausführbaren Datei |
| Private Bytes sind hoch, wachsen aber bei wiederholter Verarbeitung nicht | Pool oder Cache, der den Höchststand hält | Obergrenze, Wiederverwendung, Stabilität nach dem Peak |
Das Wichtigste an dieser Tabelle ist, nicht einzelne Werte, sondern Kombinationen zu lesen.
11. Praktisches Vorgehen bei der Untersuchung eines Speicherlecks
Die Untersuchung läuft in fünf Schritten: Vergleichsbedingungen festlegen, gleichzeitig aufzeichnen, die gewachsene Kennzahl bestimmen, die Aufschlüsselung prüfen, vor und nach der Korrektur vergleichen. Gehen Sie nicht sofort zum Dump, nur weil ein Wert groß ist; grenzen Sie zuerst ein, was wächst.
11.1. Zuerst Reproduktionsbedingungen und stationären Punkt festlegen
Dass etwas über Tage wächst, reicht zum Vergleich nicht. Legen Sie zuerst Folgendes fest, damit sich Normal- und Problemversion unter denselben Bedingungen vergleichen lassen.
- Wie weit das Aufwärmen nach dem Start einbezogen wird
- Der Inhalt eines Zyklus
- Wie viele Sekunden nach einem Zyklus gewartet wird
- Wie viele Wiederholungen nötig sind, bis die Cache-Obergrenze erreicht ist
- Ob Normal- und Problemversion dieselbe Eingabe verwenden können
11.2. Prozess und System gleichzeitig aufzeichnen
Halten Sie mindestens Folgendes zur selben Zeit fest.
- Working Set des Ziels
- Private Bytes des Ziels
- Virtual Bytes des Ziels
- Committed Bytes / Commit Limit des Systems
- Available MBytes
- Pages Input/sec
- Handle-Zahl, Thread-Zahl
- Anzahl der Bedienungen oder Verarbeitungsschritte
Bleiben die Private Bytes des Prozesses stabil, während nur das System-Commit wächst, müssen Sie den Blick auf andere Prozesse, Kernel, Treiber, Shared Sections und Ähnliches erweitern.
11.3. Zuerst festlegen, welche Dimension wächst
- Nur Working Set: residente Seiten, gemeinsame oder dateibasierte Seiten, Trim und erneutes Einlesen
- Private Bytes: prozessprivates Commit
- Nur Virtual Bytes: Reserve, Mapping, Fragmentierung des Adressraums
- Nur System Commit: einschließlich anderer Prozesse und der Kernel-Seite
- Nonpaged Pool: Treiber- und Kernel-Seite
- Handles / GDI / USER: Ressourcenlecks außerhalb des Speichers
Überspringen Sie diese Reihenfolge und gehen Sie sofort zum Dump, lesen Sie große Mengen Information, während das eigentliche Ziel noch falsch ist.
11.4. Zur Aufschlüsselung übergehen
- Nativer Prozess: VMMap, WinDbg, Application Verifier, Heap-Trace
- .NET:
dotnet-counters,dotnet-gcdump,dotnet-dump, PerfView - Gesamtes System: RAMMap, PerfMon, WPR/WPA
- Kernel-Pool: PoolMon, WinDbg
VMMap zeigt den committeten virtuellen Speicher eines Prozesses und das jeweils zugeordnete Working Set nach Typ. Wie weit sich das Wachstum der Private Bytes auf Heap, Private Data, Managed Heap oder Mapped File eingrenzen lässt, ändert den Aufwand der weiteren Untersuchung erheblich.17
11.5. Nach der Korrektur den Verlauf unter denselben Bedingungen vergleichen
Unterschiedliche Spitzenwerte vor und nach der Korrektur reichen nicht. Unterschiedliche Startwerte kehren das Bild leicht um. Gleichen Sie die folgenden Bedingungen an und vergleichen Sie Untergrenze und Steigung nach jedem Zyklus.
- Derselbe Startzustand
- Dieselbe Eingabe
- Dieselbe Anzahl von Bedienungen
- Dieselbe Wartezeit
- Dasselbe Abtastintervall
Der Beweis, dass ein Leck behoben ist, lautet nicht, dass der Maximalwert kleiner geworden ist, sondern dass die Zunahme bei wiederholter gleicher Last konvergiert.
12. Häufige Missverständnisse anders formuliert
Missverständnis 1: Der Speicherwert im Task-Manager entspricht der von der App insgesamt zugewiesenen Menge
Umformulierung: Prüfen Sie, welche Spalte gemeint ist. Die Working-Set-Familie ist die derzeit im RAM residente Menge, die Commit-Size-Familie die dem Prozess eigene Commit-Menge.
Missverständnis 2: Private Bytes entspricht der Byte-Zahl auf der Auslagerungsdatei
Umformulierung: Private Bytes ist die private Commit Charge. Es ist eine logische Versprechensmenge, die sowohl Seiten im RAM als auch Seiten umfasst, die bei Bedarf über die Auslagerungsdatei gestützt werden.
Missverständnis 3: Commit X/Y entspricht der Nutzung der Auslagerungsdatei / der Kapazität der Auslagerungsdatei
Umformulierung: X ist die systemweite Commit Charge, Y das Commit Limit. Die Auslagerungsdatei erweitert Y, aber X ist nicht eins zu eins die Nutzung auf dem Datenträger.
Missverständnis 4: Ein hoher Wert bei Page Faults/sec bedeutet, dass auf den Datenträger ausgelagert wird
Umformulierung: Soft Faults sind enthalten. Ob Datenträger-E/A stattfindet, prüfen Sie über Pages Input/sec, Page Reads/sec und die Datenträgerlatenz.
Missverständnis 5: Wenig freier RAM bedeutet Speichermangel
Umformulierung: Betrachten Sie Available, Standby, Hard Paging und die Antwortzeit. RAM mit wiederverwendbarem Cache zu füllen ist normal.
Missverständnis 6: Ein verkleinertes Working Set bedeutet, dass ein Speicherleck behoben wurde
Umformulierung: Es wurden möglicherweise nur Seiten aus dem RAM verdrängt. Prüfen Sie, ob Private Bytes und das Halten innerhalb des Heaps gesunken sind.
Missverständnis 7: Ein Anstieg bei Private Bytes bestätigt ein Leck
Umformulierung: Erst wenn Sie prüfen, ob wiederholte gleiche Last konvergiert, welche Art von Speicher gewachsen ist und ob es sich um freigebbaren Cache handelt, lässt sich urteilen.
13. Zusammenfassung
Zuerst festlegen, was die Zahl zählt
Die Windows-Speicherauslastung ist keine einzelne Zahl. Trennen Sie Adressraum, Commit, RAM-Residenz und gemeinsame Nutzbarkeit.
Das Working Set sind die derzeit im RAM liegenden Seiten und enthält Private und Shared. Das Private Working Set sind davon die dem Prozess eigenen residenten Seiten. Private Bytes dagegen ist die dem Prozess eigene Commit Charge, weder die derzeit im RAM liegende Menge noch die tatsächlich in die Auslagerungsdatei geschriebene Menge.
Als Nächstes Zuweisung, Residenz und Paging getrennt lesen
Eine reservierte virtuelle Adresse, eine committete Seite und eine Seite, die tatsächlich berührt wurde und ins Working Set gelangt ist, sind getrennte Stufen.
Committed X/Y zeigt die systemweite Commit Charge / das Commit Limit. Die Auslagerungsdatei stützt vor allem die Erweiterung des Commit Limit, das Auslagern geänderter Seiten und Absturzabbilder.
Ein Page Fault ist normaler Betrieb, und ein Soft Fault liest nicht vom Datenträger. Auch Hard Faults können nicht nur aus der Auslagerungsdatei, sondern auch aus EXE, DLL und gemappten Dateien entstehen.
In der Untersuchung Untergrenze, Steigung und Aufschlüsselung nach derselben Last vergleichen
Ein Speicherleck wird nicht anhand der Größe zu einem Zeitpunkt bewiesen, sondern anhand von Untergrenze und Steigung nach derselben Last sowie der Aufschlüsselung.
Grundsätzlich gilt: VMMap für die Aufschlüsselung eines einzelnen Prozesses, RAMMap für den physischen RAM des gesamten Systems, PerfMon für eine Zeitreihe, und ein spezialisiertes Dump-Werkzeug für das Innere der Laufzeitumgebung.
Wenn Sie das nächste Mal im Task-Manager merken, dass der Speicher wächst, stellen Sie sich zuerst diese Frage.
Wächst das Working Set, Private Bytes, Virtual Bytes oder der System Commit?
Allein diese Frage macht den Einstieg in die Untersuchung erheblich genauer.
Verwandte Artikel
- GC-Wartezeit von einem Speicherleck in .NET unterscheiden — Praktisches Vorgehen, um wachsenden Speicher zu beobachten, zu vergleichen und zu beweisen
- Process Explorer / Handle / VMMap in der Praxis — Hängern, Lecks und Datei wird verwendet vom aktuellen Zustand aus nachjagen
- Fallstricke bei Shared Memory und Best Practices — Interprozess-Sharing unter Windows sicher entwerfen
- Verzögertes Schreiben im Windows Cache Manager — Von WriteFile bis zur Übernahme auf den Datenträger
- Warum Windows-Apps nach Langzeitbetrieb durch Handle-Lecks abstürzen, und was dagegen hilft
Verwandte Beratungsleistungen
Die KomuraSoft LLC übernimmt Ursachenuntersuchungen zu wachsendem Speicherverbrauch von Windows-Anwendungen, Leistungseinbußen nach Langzeitbetrieb, OutOfMemory in 32-Bit-Prozessen sowie Speicherengpässen, die nur in der Umgebung eines Kunden auftreten, unter Einsatz von PerfMon, VMMap, RAMMap, WinDbg und .NET-Diagnosewerkzeugen. Wir belassen es nicht bei der Feststellung, dass der Speicher hoch ist, sondern grenzen ein, welcher Bereich durch welche Operation warum wächst und von wo aus er referenziert oder gehalten wird.
- Windows-Anwendungsentwicklung
- Fehleruntersuchung und Ursachenanalyse
- Technische Beratung und Design-Review
- Kontakt
Referenzlinks
-
Microsoft Learn, Working Set. Dazu, dass das Working Set eines Prozesses die Menge der derzeit im physischen Speicher residenten Seiten ist, einschließlich gemeinsam nutzbarer Seiten; zum Unterschied zwischen Soft und Hard Page Faults; zu Transition-Seiten; sowie zum Entfernen von Seiten aus dem Working Set. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, PROCESS_MEMORY_COUNTERS_EX2 structure. Zu den Definitionen von WorkingSetSize, PrivateWorkingSetSize, PrivateUsage und SharedCommitUsage sowie dazu, dass PagefileUsage und PrivateUsage beide die Commit Charge des Prozesses darstellen. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Introduction to page files. Dazu, dass die Auslagerungsdatei das Auslagern geänderter Seiten, Systemabsturzabbilder und die Erweiterung des System Commit Limit stützt; zu den Definitionen von System Commit Charge und Commit Limit; sowie zur Messung über Task-Manager und Leistungsindikatoren. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Page State. Zu den Zuständen Free, Reserved und Committed einer virtuellen Seite sowie dazu, dass Reserved-Seiten kein zugeordnetes physisches Speicherobjekt besitzen und nicht zugänglich sind. ↩ ↩2
-
Microsoft Learn, VirtualAlloc function. Zum Unterschied zwischen MEM_RESERVE und MEM_COMMIT; dazu, dass das Committen gegen den Gesamtspeicher und die Auslagerungsdateien des Systems angerechnet wird; sowie dazu, dass die tatsächliche physische Seite unter Umständen erst beim ersten Zugriff zugewiesen wird. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, How to determine the appropriate page file size for 64-bit versions of Windows. Dazu, dass die Größe der Auslagerungsdatei von der Spitzen-Commit-Charge und den Anforderungen an Absturzabbilder abhängt; dazu, dass Hard Page Faults nicht nur von der Auslagerungsdatei, sondern auch von EXE-, DLL- und speicherabgebildeten Dateien lesen; sowie zu den zugehörigen Leistungsindikatoren. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Virtual Address Space. Dazu, dass jeder Prozess einen eigenen, unabhängigen virtuellen Adressraum und eine eigene Seitentabelle besitzt und eine virtuelle Adresse keine physische Adresse selbst ist. ↩
-
Microsoft Learn, Memory Limits for Windows and Windows Server Releases. Dazu, dass der virtuelle Adressraum eines 32-Bit-Prozesses im Benutzermodus normalerweise 2GB beträgt und unter 64-Bit-Windows je nach IMAGE_FILE_LARGE_ADDRESS_AWARE entweder 2GB oder 4GB wird. ↩
-
Microsoft Learn, SetProcessWorkingSetSize function. Dazu, dass der minimale und maximale Wert des Working Set keine Residenz garantieren; dazu, dass sich ein Working Set leeren lässt; sowie dazu, dass übermäßige Einstellungen oder Operationen die Systemleistung verschlechtern können. ↩
-
Microsoft Learn, Memory Performance Information. Zum Zusammenhang zwischen Windows-Leistungsindikatoren, Speicherverwaltungs-APIs und der Anzeige im Task-Manager, einschließlich Working Set, Working Set - Private und Private Bytes des Process-Objekts sowie Committed Bytes und Commit Limit des System-Objekts. ↩
-
Microsoft Learn, MapViewOfFile function. Dazu, dass bei
FILE_MAP_COPYjede Seite potenziell Copy-on-write werden kann, weshalb die Commit Charge für die gesamte View bereits beim Mappen reserviert wird, um sie über die Auslagerungsdatei absichern zu können. ↩ ↩2 -
Microsoft Learn, Understanding Node Metrics and Properties in HPC Cluster Manager. Dazu, dass Available Physical Memory als Summe der Listen Zeroed, Free und Standby berechnet wird, sowie zur Bedeutung der einzelnen Seitenlisten. ↩
-
Microsoft Sysinternals, RAMMap. Zur Analyse der Nutzung des physischen Windows-Speichers nach Verwendungszweck, Seitenliste, Prozess, Priorität, physischer Seite und Datei. ↩ ↩2
-
Microsoft Learn, Process.WorkingSet64 Property. Dazu, dass
WorkingSet64das Working Set des Prozesses in Bytes zurückgibt und dem Working-Set-Leistungsindikator des Process-Objekts entspricht. ↩ -
Microsoft Learn, Process.PrivateMemorySize64 Property. Dazu, dass
PrivateMemorySize64den nicht mit anderen Prozessen teilbaren, prozesseigenen Speicher zurückgibt und dem Private-Bytes-Leistungsindikator entspricht. ↩ -
Microsoft Learn, Process.VirtualMemorySize64 Property. Dazu, dass
VirtualMemorySize64die Menge des virtuellen Speichers des Prozesses zurückgibt und dem Virtual-Bytes-Leistungsindikator entspricht. ↩ -
Microsoft Sysinternals, VMMap. Zur Aufschlüsselung des committeten virtuellen Speichers eines Prozesses nach Typ, zur Anzeige des jeweils zugewiesenen physischen Speichers (Working Set) sowie zu einer detaillierten Speicherzuordnung. ↩ ↩2
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
Die Tiefen des Windows-Speichers (Teil 2) — Das Leben einer physischen Seite: fünf Listen und die Wahrheit über die Auslagerungsdatei
Dieser Artikel verbindet die PFN-Datenbank, Standby, Modified, Speicherkompression und die Auslagerungsdatei und erklärt, wohin eine phys...
Die Tiefen des Windows-Speichers (Teil 1) — Der Moment, in dem eine virtuelle Adresse zu physischem RAM wird: ein Page Fault von Anfang bis Ende
VirtualAlloc, VAD, Seitentabelle, TLB, Demand-Zero und Hard Page Faults verbinden und den Moment erklären, in dem eine virtuelle Adresse ...
Das Netzwerk läuft, aber Windows sagt „Kein Internet“ — NCSI, DNS, Proxy und VPN unter Windows eingrenzen
Warum Windows „Kein Internet“ meldet, während das Netzwerk läuft — ausgehend vom NCSI-Urteil. DNS, Proxy, VPN und Anmeldeportale mit rein...
Was Schnellstart wirklich tut — Warum „Herunterfahren“ unter Windows nicht dasselbe ist wie ein Neustart
Ein Windows-Herunterfahren ist standardmäßig ein Hybrid-Herunterfahren und speichert Kernel und Treiber in hiberfil.sys. Warum nur ein Ne...
Time Travel Debugging — Langlaufende Fehler, die sich nicht reproduzieren, aufzeichnen und zurückspulen
Ein Fehler, der nur einmal im Monat auftritt, hinterlässt im Absturz-Dump nur das Ergebnis. Mit Time Travel Debugging (TTD) in WinDbg zei...
Verwandte Themen
Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.
Technische Windows-Themen
Portal zu Windows-Entwicklung, Fehleranalyse und der Nutzung bestehender Assets.
Leistungen zu diesem Thema
Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.
Windows-App-Entwicklung
Geschäftsanwendungen, Geräteintegration und Kommunikationstools von den Anforderungen bis zur Umsetzung.
Häufige Fragen
Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.
- Zeigt die Spalte Speicher im Task-Manager den gesamten von einer App belegten Speicher?
- Nein. Der Task-Manager hat mehrere Speicherspalten, darunter die Working-Set-Familie, die Private-Working-Set-Familie und Commit Size, und die Bedeutung hängt davon ab, welchen Bildschirm und welche Spalte Sie betrachten. Working Set sind die Seiten, die derzeit im RAM liegen; Private Bytes oder Commit Size ist die für diesen Prozess spezifische Commit-Menge. Lesen Sie eine einzelne Spalte Speicher nicht als die gesamte von einer App belegte Kapazität oder als Größe eines Lecks.
- Was ist der Unterschied zwischen Working Set und Private Bytes?
- Working Set ist die Menge der für den Prozess sichtbaren Seiten, die derzeit im physischen RAM resident sind, einschließlich gemeinsam nutzbarer Seiten wie DLL-Code oder speicherabgebildeter Dateien. Private Bytes ist die Menge des ausschließlich von diesem Prozess genutzten committeten Speichers, unabhängig davon, ob er derzeit im RAM resident ist. Beide sind daher nie gleich groß, und keiner der beiden Werte ist durchgängig größer als der andere.
- Bedeutet Committed 18/32GB im Task-Manager, dass 18GB in die Auslagerungsdatei geschrieben wurden?
- Nein. Der linke Wert ist die Commit-Menge, die das gesamte System derzeit zu unterstützen verspricht, der rechte Wert ist die Commit-Obergrenze, die das System stützen kann. Die Obergrenze ergibt sich grob aus RAM plus Auslagerungsdatei, aber nicht die gesamte linke Summe liegt tatsächlich in der Auslagerungsdatei. Viele committete Seiten liegen im RAM, und manchen committeten Seiten wurde noch nie eine physische Seite zugewiesen. Seiten dagegen, die aus ihrer Ursprungsdatei neu geladen werden können, etwa EXE-, DLL- und speicherabgebildete Dateien, erhöhen das Working Set nicht zwangsläufig um denselben Betrag wie das private Commit.
- Kann OutOfMemory auftreten, obwohl freier RAM verfügbar ist?
- Ja. Eine Zuweisung kann aus anderen Gründen als physischem RAM-Mangel fehlschlagen, etwa weil ein 32-Bit-Prozess seinen virtuellen Adressraum erschöpft hat, kein zusammenhängender freier Adressbereich in ausreichender Größe existiert, die System-Commit-Obergrenze erreicht ist oder ein Job-Objekt beziehungsweise die Laufzeitumgebung eine eigene Grenze hat. Insbesondere ein 32-Bit-Prozess unter 64-Bit-Windows ist ohne Large Address Awareness normalerweise auf 2GB virtuellen Adressraum im Benutzermodus begrenzt.
- Wird Windows schneller, wenn die Auslagerungsdatei deaktiviert wird?
- Im Allgemeinen lässt sich das nicht pauschal bejahen. Das Deaktivieren der Auslagerungsdatei senkt die Commit-Obergrenze des Systems, erschwert das Auslagern ungenutzter geänderter Seiten aus dem RAM und wirkt sich auch auf die Konfiguration von Absturzabbildern aus. Die Größe der Auslagerungsdatei sollte anhand der Spitzen-Commit-Menge und des benötigten Absturzabbilds festgelegt werden. Sie ist keine Einstellung, die man ohne Grund deaktiviert.
- Bedeutet ein hoher Wert bei Page Faults/sec einen Speichermangel?
- Das lässt sich daraus allein nicht entscheiden. Bei Page Faults gibt es Soft Faults, die sich über Standby-Seiten im RAM oder mit einem anderen Prozess gemeinsam genutzte Seiten auflösen lassen, und Hard Faults, die von der Festplatte lesen. Betrachten Sie nicht Page Faults/sec allein, sondern prüfen Sie Pages Input/sec, Page Reads/sec, Available MBytes, die Datenträgerlatenz und die Verarbeitungszeit gemeinsam auf derselben Zeitachse.
Autorenprofil
Profilseite des Artikelautors.
Go Komura
Geschäftsführer von KomuraSoft LLC
Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.