Wie funktioniert die Speicher-/Commit-Gebühr in Windows 10?

Wie funktioniert die Speicher-/Commit-Gebühr in Windows 10?

Diese Frage wird durch die folgenden regelmäßig beobachteten Phänomene ausgelöst, für die ich gerne eine Erklärung finden würde:

  1. Das aktuelle Commit ist regelmäßig höher als die physische Nutzung + Auslagerungsdateigröße. Was ist da los? Sollte das nicht unmöglich sein? [Das könnte an der Komprimierung liegen. Was die Frage in folgende verwandelt: Warum steigt das Commit-Limit dann nicht an oder so? D. h., was ist der Sinn der Komprimierung, wenn sie nicht bei der Speichernutzung hilft?]
  2. Manchmal erreicht dies extreme Werte, bei denen der aktuelle Commit mehr als das Doppelte der physischen Speichernutzung beträgt.
  3. Wenn die Commit-Ladung voll ist und Windows mich auffordert, Dinge zu schließen, ist der physische Speicher die meiste Zeit bei etwa 60 %. Das scheint schrecklich ineffizient.

Dies ist unter Windows 10 der Fall, wie Process Explorer meldet.

Die ultimative Frage, die ich beantworten möchte, lautet: Kann ich darauf verzichten, meine Auslagerungsdatei künstlich auf ein Niveau aufzublähen, das meine SSD mit ihrem geringen Speicherplatz nicht bewältigen kann, nur damit ich meinen physischen Speicher tatsächlich effektiv nutzen kann? (Oder sogar, wenn er nicht so voll wäre. Das heißt, ich möchte Vorschläge wie „Machen Sie X/Y/Z mit Ihrer Auslagerungsdatei.“)

Antwort1

Dies ist eigentlich ziemlich einfach, wenn man einmal verstanden hat, dass die Commit-Gebühr nurPotenzial- aber "garantiert verfügbar, wenn Sie es wollen" - Verwendung des virtuellen Speichers, während der "private Arbeitssatz" - der im Wesentlichen der RAM ist, der vom "festgelegten" Speicher verwendet wird -tatsächlichebenso wie der Auslagerungsdateispeicherplatz. (Das ist aber nicht die gesamte RAM-Nutzung, denn es gibt auch andere Dinge, die RAM nutzen.)

Nehmen wir an, wir sprechen von 32-Bit-Systemen, sodass der maximale virtuelle Adressraum, der jedem Prozess zur Verfügung steht, normalerweise 2 GiB beträgt. (Es gibt keinen wesentlichen Unterschied inbeliebigdes Folgenden für 64-Bit-Systeme, außer dass die Adressen und Größen größer sein können – viel größer.)

Nehmen wir nun an, dass ein in einem Prozess ausgeführtes Programm VirtualAlloc (eine Win32-API) verwendet, um 2 MiB virtuellen Speicher zu „belegen“. Wie zu erwarten, wird dies als zusätzliche 2 MiB Belegungskosten angezeigt und es stehen im Prozess 2 MiB weniger Bytes virtuellen Adressraums für zukünftige Zuweisungen zur Verfügung.

Es wird jedoch noch kein physischer Speicher (RAM) verwendet!

Der VirtualAlloc-Aufruf gibt dem Aufrufer die Startadresse der zugewiesenen Region zurück. Die Region liegt irgendwo im Bereich von 0x10000 bis 0x7FFEFFFF, also etwa 2 GiB. (Die ersten und letzten 64 KiB oder 0x10000 in Hexadezimalwert von Vas in jedem Prozess werden nie zugewiesen.)

Aber nochmals - es gibt keinen tatsächlichen physischen Nutzen von 2 MiBLagerungnoch nicht! Nicht im RAM, nicht einmal in der Auslagerungsdatei. (Es gibt eine winzige Struktur namens „Virtual Address Descriptor“, die den Startwert und die Länge der privaten, festgeschriebenen Region beschreibt.)

Da haben Sie es also! Die Commit-Gebühr ist gestiegen, die physische Speichernutzung jedoch nicht.

Dies lässt sich mit dem Tool „Sysinternals“ leicht demonstrieren testlimit.

Nehmen wir an, das Programm speichert irgendwann später etwas (z. B. einen Speicherschreibvorgang) in dieser Region (egal wo). Es gibt noch keinen physischen Speicher unter dieser Region, daher verursacht ein solcher Zugriff eineSeitenfehler. Als Reaktion darauf wird der Speichermanager des Betriebssystems, insbesondere die Seitenfehlerbehandlungsroutine (kurz „Pager“... sie heißt MmAccessFault), Folgendes tun:

  1. eine bereits „verfügbare“ physische Seite zuweisen
  2. Richten Sie den Seitentabelleneintrag für die aufgerufene virtuelle Seite ein, um die virtuelle Seitennummer mit der neu zugewiesenen physischen Seitennummer zu verknüpfen.
  3. füge die physische Seite zum Prozess hinzu privatWorkingset
  4. und den Seitenfehler beheben, wodurch die Anweisung, die den Fehler verursacht hat, erneut versucht wird.

Sie haben jetzt eine Seite (4 KiB) in den Prozess „einen Fehler“ gemacht. Und die physische Speichernutzung wird entsprechend zunehmen und der „verfügbare“ RAM wird abnehmen. Die Commit-Gebühr ändert sich nicht.

Wenn die Seite eine Zeit lang nicht aufgerufen wurde und der RAM-Bedarf hoch ist, kann später Folgendes passieren:

  1. das Betriebssystem entfernt die Seite aus dem Arbeitssatz des Prozesses.
  2. da darauf geschrieben wurde, seit es in den Arbeitssatz aufgenommen wurde, wird es in die geänderte Seitenliste aufgenommen (sonst würde es in die Standby-Seitenliste aufgenommen). Der Seitentabelleneintrag spiegelt immer noch die physische Seitennummer der RAM-Seite wider, aber jetzt ist sein „gültiges“ Bit gelöscht, sodass beim nächsten Verweis darauf ein Seitenfehler auftritt.
  3. wenn die geänderte Seitenliste einen kleinen Schwellenwert erreicht, eingeänderter SeitenschreiberThread im „System“-Prozess wird aktiviert und speichert den Inhalt der geänderten Seiten in der Auslagerungsdatei (vorausgesetzt, Sie haben eine) und …
  4. nimmt diese Seiten aus der geänderten Liste und setzt sie auf die Standby-Liste. Sie werden nun als Teil des „verfügbaren“ RAM betrachtet; vorerst haben sie jedoch noch ihren ursprünglichen Inhalt aus der Zeit, als sie sich in ihren jeweiligen Prozessen befanden. Auch hier ändert sich die Commit-Gebühr nicht, aber die RAM-Nutzung und der private Arbeitssatz des Prozesses werden sinken.
  5. Seiten auf der Warteliste können nunumfunktioniert, das heißt, es wird für etwas anderes verwendet – beispielsweise zum Beheben von Seitenfehlern von einem beliebigen Prozess im System oder von SuperFetch. Allerdings...
  6. Wenn ein Prozess, der eine Seite an die geänderte oder Standby-Liste verloren hat, versucht, erneut darauf zuzugreifen, bevor die physische Seite wiederverwendet wurde (d. h. sie hat noch ihren ursprünglichen Inhalt), wird der Seitenfehler behoben, ohne dass von der Festplatte gelesen werden muss. Die Seite wird einfach wieder in den Arbeitssatz des Prozesses eingefügt und der Seitentabelleneintrag wird „gültig“ gemacht. Dies ist ein Beispiel für einen „weichen“ oder „billigen“ Seitenfehler. Wir sagen, dass die Standby- und geänderten Listen einen systemweiten Cache von Seiten bilden, die wahrscheinlich bald wieder benötigt werden.

Wenn Sie keine Auslagerungsdatei haben, werden die Schritte 3 bis 5 wie folgt geändert:

  1. Die Seiten befinden sich in der geänderten Liste, da es keinen Platz gibt, um ihren Inhalt zu schreiben.

  2. Die Seiten befinden sich in der geänderten Liste, da es keinen Platz gibt, um ihren Inhalt zu schreiben.

  3. Die Seiten befinden sich in der geänderten Liste, da es keinen Platz gibt, um ihren Inhalt zu schreiben.

Schritt 6 bleibt gleich, da Seiten auf der geänderten Liste als „weicher“ Seitenfehler an den Prozess zurückgeschickt werden können, der sie verloren hat. Wenn das jedoch nicht geschieht, bleiben die Seiten auf der geänderten Liste, bis der Prozess den entsprechenden virtuellen Speicher freigibt (möglicherweise weil der Prozess beendet wird).

Es gibt noch andere Verwendungsmöglichkeiten für virtuellen Adressraum und RAM, außer für privaten, festgeschriebenen Speicher. Es gibtzugeordnetvirtueller Adressraum, für den der Backing Store eine bestimmte Datei und nicht die Auslagerungsdatei ist. Die Seiten von zugeordneten VAS, die ausgelagert werden, werden in der RAM-Nutzung reflektiert, aber zugeordneter Speicher trägt nicht zur Commit-Gebühr bei, da die zugeordnete Datei den Backing Store bereitstellt: Jeder Teil des zugeordneten Bereichs, der sich nicht im RAM befindet, wird einfach in der zugeordneten Datei gespeichert. Ein weiterer Unterschied besteht darin, dass die meisten Dateizuordnungen zwischen Prozessen gemeinsam genutzt werden können; eine gemeinsam genutzte Seite, die sich bereits im Speicher eines Prozesses befindet, kann einem anderen Prozess hinzugefügt werden, ohne dass dafür erneut auf die Festplatte zugegriffen werden muss (ein weiterer Soft-Page-Fault).

Und da istnicht auslagerbarvas, für das es keinen Sicherungsspeicher gibt, da es immer im RAM resident ist. Dies trägt sowohl zur gemeldeten RAM-Nutzung als auch zur „Commit-Gebühr“ bei.

Dies scheint an der Komprimierung zu liegen. Damit ändert sich die Frage zu: Warum wird das Commit-Limit dann nicht erhöht oder so? Was ist also der Sinn der Komprimierung, wenn sie nicht bei der Speichernutzung hilft?

Nein. Es hat nichts mit Komprimierung zu tun. Die Speicherkomprimierung in Windows erfolgt als Zwischenschritt auf Seiten, die sonst in die Auslagerungsdatei geschrieben würden. Tatsächlich ermöglicht es diegeänderte Seitenlisteweniger RAM zu verwenden, um mehr Sachen unterzubringen, auf Kosten der CPU-Zeit, aber mit weitaus höherer Geschwindigkeit als Pagefile I/O (sogar auf einer SSD). Da das Commit-Limit berechnet wird ausgesamtRAM + Auslagerungsdateigröße, nicht RAM-Nutzung + Auslagerungsdateinutzung, dies hat keine Auswirkungen auf das Commit-Limit. Das Commit-Limit ändert sich nicht, je nachdem, wie viel RAM verwendet wird oder wofür es verwendet wird.

Wenn die Commit-Ladung voll ist und Windows mich auffordert, Dinge zu schließen, ist der physische Speicher die meiste Zeit bei etwa 60 %. Das scheint schrecklich ineffizient.

Es liegt nicht daran, dass Windows ineffizient ist. Es liegt an den Apps, die Sie ausführen. Sie verbrauchen viel mehr Daten, als sie tatsächlich nutzen.

Der Grund für den gesamten Mechanismus „Commit Charge“ und „Commit Limit“ ist folgender: Wenn ich VirtualAlloc aufrufe, soll ich den Rückgabewert prüfen, um zu sehen, ob er ungleich Null ist. Wenn er Null ist, bedeutet das, dass mein Zuweisungsversuch fehlgeschlagen ist, wahrscheinlich weil die Commit Charge dadurch das Commit Limit überschritten hätte. Ich soll etwas Vernünftiges tun, z. B. versuchen, weniger zu committen oder das Programm sauber zu beenden.

Wenn VirtualAlloc einen Wert ungleich Null zurückgibt, also eine Adresse, dann sagt mir das, dass das System eine Garantie gegeben hat - eine Zusage, wenn Sie so wollen - dass, egal wie viele Bytes ich angefordert habe, beginnend bei dieser Adresse,wird seinverfügbar, wenn ich darauf zugreifen möchte; dass es einen Ort gibt, an dem alles gespeichert werden kann - entweder im RAM oder in der Auslagerungsdatei. D. h. es gibt keinen Grund, beim Zugriff auf irgendetwas in dieser Region mit Fehlern zu rechnen. Das ist gut, denn es wäre nicht vernünftig, von mir zu erwarten, dass ich bei jedem Zugriff auf die zugewiesene Region prüfe, ob es funktioniert hat.

Die Analogie der „Bargeld verleihenden Bank“

Es ist ein bisschen wie eine Bank, die Kredite vergibt, allerdings ausschließlich auf der Basis von Bargeld. (So funktionieren echte Banken natürlich nicht.)

Angenommen, die Bank hat zu Beginn eine Million Dollar in bar zur Verfügung. Die Leute gehen zur Bank und beantragen Kreditlinien in unterschiedlichen Beträgen. Angenommen, die Bank genehmigt mir eine Kreditlinie von 100.000 Dollar (ich erstelle eine private, zugesicherte Region); das bedeutet nicht, dass tatsächlich Bargeld den Tresor verlassen hat. Wenn ich später tatsächlich einen Kredit über beispielsweise 20.000 Dollar aufnehme (ich greife auf eine Teilmenge der Region zu), wird der Bank Bargeld entzogen.

Aber ob ich nun Kredite aufnehme oder nicht, die Tatsache, dass mir maximal 100.000 Dollar genehmigt wurden, bedeutet, dass die Bank anschließend nur weitere Kreditlinien im Wert von insgesamt 900.000 Dollar für alle ihre Kunden genehmigen kann. Die Bank wird keine Kredite genehmigen, die ihre Barreserven übersteigen (d. h. sie wird nichtÜberlastungsie), denn das würde bedeuten, dass die Bank einen zuvor genehmigten Kreditnehmer abweisen müsste, wenn dieser später auftaucht und beabsichtigt, einenihreKredit. Das wäre sehr schlecht, denn die Bank hat bereitsengagiertDie Gewährung dieser Kredite würde zu einem erheblichen Reputationsverlust der Bank führen.

Ja, das ist „ineffizient“ im Hinblick auf die Verwendung des Geldes durch die Bank. Und je größer die Diskrepanz zwischen den Kreditlinien, die den Kunden bewilligt werden, und den Beträgen, die sie tatsächlich leihen, ist, desto weniger effizient ist es. Aber diese Ineffizienz ist nicht die Schuld der Bank; es ist die „Schuld“ der Kunden, die so hohe Kreditlinien beantragen, aber nur kleine Kredite aufnehmen.

Das Geschäftsmodell der Bank besteht darin, dass sie einen zuvor genehmigten Kreditnehmer nicht einfach abweisen kann, wenn er zur Kreditaufnahme erscheint - das wäre für den Kunden "fatal". Deshalb führt die Bank sorgfältig Buch darüber, wie viel des Kreditbetrags "zugesagt" wurde.

Ich nehme an, dass das Erweitern der Auslagerungsdatei oder das Hinzufügen einer weiteren so wäre, als würde die Bank losgehen, mehr Bargeld besorgen und es dem Kreditfonds hinzufügen.

Wenn Sie in dieser Analogie zugeordneten und nicht auslagerbaren Speicher modellieren möchten ... nicht auslagerbarer Speicher ist wie ein kleiner Kredit, den Sie aufnehmen und offen lassen müssen, wenn Sie Ihr Konto eröffnen. (Die nicht auslagerbaren Strukturen, die jeden neuen Prozess definieren.) Zugeordneter Speicher ist, als ob Sie Ihr eigenes Bargeld mitbringen (die Datei, die zugeordnet wird) und es bei der Bank hinterlegen und dann immer nur einen Teil davon abheben (einlagern). Warum nicht alles auf einmal einlagern? Ich weiß nicht, vielleicht haben Sie in Ihrer Brieftasche nicht genug Platz für all das Bargeld. :) Dies hat keinen Einfluss auf die Möglichkeit anderer, Geld zu leihen, da sich das von Ihnen eingezahlte Bargeld auf Ihrem eigenen Konto befindet und nicht im allgemeinen Kreditfonds. Diese Analogie beginnt ungefähr hier zusammenzubrechen, insbesondere wenn wir über gemeinsam genutzten Speicher nachdenken, also übertreiben Sie es nicht.

Zurück zum Windows-Betriebssystem: Die Tatsache, dass Sie einen Großteil Ihres RAM „zur Verfügung“ haben, hat nichts mit Commit-Gebühren und Commit-Limit zu tun. Wenn Sie sich dem Commit-Limit nähern, bedeutet dies, dass das Betriebssystem bereits Commit-Vorgänge ausgeführt hat – d. h. versprochen, zur Verfügung zu stellenauf Anfrage - so viel Speicher. Der Speicherplatz muss noch nicht vollständig belegt sein, damit das Limit durchgesetzt wird.

Kann ich darauf verzichten, meine Auslagerungsdatei künstlich auf ein Niveau aufzublähen, das meine SSD mit ihrem knappen Speicherplatz nicht bewältigen kann, nur damit ich meinen physischen Speicher tatsächlich effektiv nutzen kann? (Oder sogar, wenn er nicht so voll wäre. Das heißt, ich möchte Vorschläge wie „Machen Sie X/Y/Z mit Ihrer Auslagerungsdatei.“)

Es tut mir leid, aber wenn Sie an das Commit-Limit stoßen, können Sie nur drei Dinge tun:

  1. Erhöhen Sie Ihren RAM.
  2. Erhöhen Sie die Größe Ihrer Auslagerungsdatei.
  3. Führen Sie weniger Dinge gleichzeitig aus.

Zu Option 2: Sie könnten eine zweite Auslagerungsdatei auf einer Festplatte ablegen. Wenn die Apps nicht den gesamten zugewiesenen Speicher verwenden – was anscheinend nicht der Fall ist, da Sie so viel freien RAM sehen –, werden Sie nicht oft auf diese Auslagerungsdatei zugreifen, sodass die Leistung nicht beeinträchtigt wird, wenn Sie sie auf einer Festplatte ablegen. Wenn Sie die Langsamkeit einer Festplatte immer noch stören würde, besteht eine weitere Möglichkeit darin, eine kleine und daher billige zweite SSD zu kaufen und Ihre zweite Auslagerungsdatei darauf abzulegen. Der einzige „Showstopper“ wäre ein Laptop ohne Möglichkeit, ein zweites „nicht entfernbares“ Laufwerk hinzuzufügen. (Windows lässt Sie keine Auslagerungsdateien auf entfernbaren Laufwerken ablegen, wie etwa auf allem, was über USB angeschlossen ist.)

Hier isteine andere Antwort, die ich geschrieben habedas erklärt die Dinge aus einer anderen Richtung.

PS: Sie haben nach Windows 10 gefragt, aber ich sollte Ihnen sagen, dass es in jeder Version der NT-Familie, zurück bis NT 3.1, und auch in den Vorabversionen gleich funktioniert. Was sich wahrscheinlich geändert hat, ist die Standardeinstellung von Windows für die Auslagerungsdateigröße, von 1,5x oder 1x RAM-Größe auf viel weniger. Ich glaube, das war ein Fehler.

verwandte Informationen