Was sind private Bytes, virtuelle Bytes, Arbeitssätze?

490

Ich versuche, das Dienstprogramm perfmon windows zu verwenden, um Speicherlecks in einem Prozess zu debuggen.

So erklärt perfmon die Begriffe:

Arbeitssatz ist die aktuelle Größe des Arbeitssatzes dieses Prozesses in Byte. Der Arbeitssatz ist der Satz von Speicherseiten, die kürzlich von den Threads im Prozess berührt wurden. Wenn der freie Speicher im Computer einen Schwellenwert überschreitet, bleiben Seiten im Arbeitssatz eines Prozesses, auch wenn sie nicht verwendet werden. Wenn der freie Speicher einen Schwellenwert unterschreitet, werden Seiten aus Arbeitssätzen abgeschnitten. Wenn sie benötigt werden, werden sie vor dem Verlassen des Hauptspeichers wieder in den Arbeitssatz zurückgeführt.

Virtuelle Bytes ist die aktuelle Größe des vom Prozess verwendeten virtuellen Adressraums in Byte. Die Verwendung des virtuellen Adressraums bedeutet nicht unbedingt die entsprechende Verwendung von Festplatten- oder Hauptspeicherseiten. Der virtuelle Raum ist endlich und der Prozess kann seine Fähigkeit zum Laden von Bibliotheken einschränken.

Private Bytes ist die aktuelle Größe des von diesem Prozess zugewiesenen Speichers in Bytes, die nicht mit anderen Prozessen gemeinsam genutzt werden kann.

Das sind die Fragen, die ich habe:

Sind es die privaten Bytes, die ich messen sollte, um sicherzugehen, dass der Prozess Lecks aufweist, da keine gemeinsam genutzten Bibliotheken vorhanden sind und Lecks, falls sie auftreten, vom Prozess selbst stammen?

Wie viel Speicher belegt der Prozess insgesamt? Sind es die virtuellen Bytes oder die Summe aus virtuellen Bytes und Arbeitssatz?

Gibt es eine Beziehung zwischen privaten Bytes, Arbeitssatz und virtuellen Bytes?

Gibt es andere Tools, die eine bessere Vorstellung von der Speichernutzung geben?

pankajt
quelle
3
Ein besseres Werkzeug wäre Valgrind / Helgrind, aber leider nicht unter Windows :(
Kornel Kisielewicz
Ist es das private Byte, das ich messen sollte, um sicherzugehen, dass der Prozess ein Leck aufweist? Wenn private Bytes eines Prozesses nicht wachsen, treten keine Speicherlecks auf. Wenn sie wachsen, kann dies an Speicherlecks und an Speicherfragmentierung liegen. Ich denke, es ist schwierig zu sagen, was es genau bedeutet , wenn man das Wachstum privater Bytes betrachtet .
@SergeiKurenkov Eine Sache, die wir sagen können, ist, dass es NIE auf "Speicherfragmentierung" zurückzuführen wäre.
Jamie Hanrahan

Antworten:

517

Die kurze Antwort auf diese Frage lautet, dass keiner dieser Werte ein zuverlässiger Indikator dafür ist, wie viel Speicher eine ausführbare Datei tatsächlich verwendet, und keiner von ihnen wirklich zum Debuggen eines Speicherverlusts geeignet ist.

Privates Bytes bezieht sich auf die Größe des Speichers , dass der Prozess ausführbar ist gefragt - nicht notwendigerweise die Menge ist eigentlich mit . Sie sind "privat", da sie (normalerweise) speicherabgebildete Dateien (dh gemeinsam genutzte DLLs) ausschließen. Aber - hier ist der Haken - sie schließen den von diesen Dateien zugewiesenen Speicher nicht unbedingt aus . Es kann nicht festgestellt werden, ob eine Änderung der privaten Bytes auf die ausführbare Datei selbst oder auf eine verknüpfte Bibliothek zurückzuführen ist. Private Bytes sind auch nicht ausschließlich physischer Speicher. Sie können auf die Festplatte oder in die Liste der Standby-Seiten ausgelagert werden (dh sie werden nicht mehr verwendet, aber auch noch nicht ausgelagert).

Arbeitssatz bezieht sich auf den gesamten physischen Speicher (RAM), der vom Prozess verwendet wird. Im Gegensatz zu privaten Bytes umfasst dies jedoch auch speicherabgebildete Dateien und verschiedene andere Ressourcen, sodass die Messung noch weniger genau ist als bei privaten Bytes. Dies ist derselbe Wert, der in "Mem Usage" des Task-Managers gemeldet wird und in den letzten Jahren zu endloser Verwirrung geführt hat. Der Speicher im Arbeitssatz ist "physisch" in dem Sinne, dass er ohne Seitenfehler adressiert werden kann. Die Liste der Standby-Seiten befindet sich jedoch auch noch physisch im Speicher, wird jedoch nicht im Arbeitssatz gemeldet. Aus diesem Grund wird die "Mem-Verwendung" möglicherweise plötzlich gelöscht, wenn Sie eine Anwendung minimieren.

Virtuelle Bytes sind der gesamte virtuelle Adressraum, der vom gesamten Prozess belegt wird. Dies ähnelt dem Arbeitssatz in dem Sinne, dass er speicherabgebildete Dateien (gemeinsam genutzte DLLs) enthält, aber auch Daten in der Standby-Liste und Daten, die bereits ausgelagert wurden und sich irgendwo in einer Auslagerungsdatei auf der Festplatte befinden. Die gesamten virtuellen Bytes, die von jedem Prozess auf einem System unter hoher Last verwendet werden, summieren sich zu erheblich mehr Speicher als die Maschine tatsächlich hat.

Die Beziehungen sind also:

  • Private Bytes sind das, was Ihre App tatsächlich zugewiesen hat, umfassen jedoch die Verwendung von Auslagerungsdateien.
  • Der Arbeitssatz besteht aus nicht ausgelagerten privaten Bytes und Dateien mit Speicherzuordnung.
  • Virtuelle Bytes sind der Arbeitssatz plus ausgelagerte private Bytes und die Standby-Liste.

Hier gibt es ein anderes Problem. So wie gemeinsam genutzte Bibliotheken Speicher in Ihrem Anwendungsmodul zuweisen können, was zu potenziellen Fehlalarmen führen kann, die in den privaten Bytes Ihrer App gemeldet werden, kann Ihre Anwendung auch Speicher in den gemeinsam genutzten Modulen zuweisen , was zu falsch negativen Ergebnissen führt . Das heißt, es ist tatsächlich möglich, dass Ihre Anwendung einen Speicherverlust aufweist, der sich überhaupt nicht in den privaten Bytes manifestiert. Unwahrscheinlich, aber möglich.

Private Bytes sind eine vernünftige Annäherung der Größe des Speichers der ausführbaren Datei verwendet , und kann Hilfe verwendet wird , verengt eine Liste der potenziellen Kandidaten für ein Speicherleck; Wenn Sie sehen, dass die Anzahl ständig und endlos wächst und wächst, sollten Sie diesen Prozess auf ein Leck überprüfen. Dies kann jedoch nicht beweisen, dass ein Leck vorliegt oder nicht.

Eines der effektivsten Tools zum Erkennen / Korrigieren von Speicherlecks in Windows ist Visual Studio (der Link führt zur Seite zur Verwendung von VS für Speicherlecks, nicht zur Produktseite). Rational Purify ist eine weitere Möglichkeit. Microsoft verfügt auch über ein allgemeineres Best-Practice-Dokument zu diesem Thema. In dieser vorherigen Frage sind weitere Tools aufgeführt .

Ich hoffe das klärt ein paar Dinge auf! Das Aufspüren von Speicherlecks ist eines der schwierigsten Dinge beim Debuggen. Viel Glück.

Aaronaught
quelle
26
Ich fürchte, Ihre Antwort ist nicht ganz richtig. Private Bytes beziehen sich auf die Speichermenge (RAM), nach der die ausführbare Prozessdatei gefragt hat - nicht nur auf den physischen Speicher. Auf diese Weise können Sie sicher die meisten Fälle von Speicherverlusten untersuchen, indem Sie private Bytes überwachen. Versuchen Sie :: VisualAlloc, einen großen Teil des Speichers festzuschreiben (z. B. 1,5 G). Sie sollten sehen können, dass Ihre privaten Bytes viel größer sind als der Arbeitssatz. Dies beweist, dass Ihr "Arbeitssatz" Private Bytes plus speicherabgebildete Dateien "falsch ist.
Jay Zhu
4
Eigentlich glaube ich, dass das Schreibverständnis "Working Set ist das private Byte im Speicher plus speicherabgebildete Dateien" ist. Und private Bytes können ausgetauscht werden - Sie können private Bytes sehen, die größer sind als der physische Speicher, den Sie auf dem Computer haben.
Jay Zhu
2
@Aaronaught: Ihre erste Aussage über einen zuverlässigen Indikator, der für das Debuggen geeignet ist, ist verwirrend. Private Bytes sind ein zuverlässiger Indikator für ein Leck im Anwendungsspeicherplatz. Es kann sich um eine abhängige und indirekte DLL handeln, es handelt sich jedoch um ein Leck im Anwendungsspeicherbereich. Können Sie erklären, warum es nicht zum Debuggen verwendet werden kann? Ein vollständiger Speicherauszug des Anwendungsprozesses sollte uns mitteilen, was diesen Speicher belegt. Ich bin nicht sicher, ob ich verstehe, warum es nicht zum Debuggen verwendet werden kann. Kannst du etwas Licht ins Dunkel bringen?
G33kKahuna
@ G33kKahuna: Mir ist nicht klar, wie ein Speicherauszug Ihnen sagen würde, was den Speicher in einem sinnvollen Sinne verbraucht - es sei denn, mit "was" meinen Sie "welche Module", aber alles, was Sie haben, ist ein Schnappschuss, den Sie immer noch nicht sehen können Welches Modul verliert im Laufe der Zeit tatsächlich Speicher, es sei denn, Sie führen im Laufe der Zeit und unter streng kontrollierten Bedingungen mehrere Speicherauszüge durch. Es ist schwer, sich eine ineffizientere und unzuverlässigere Debugging-Strategie vorzustellen. Profiler sind heutzutage überall; benutze eins.
Aaronaught
1
Führen Sie eine vollständige! Objsize aus. Dies sollte alle angehefteten Objekte im unmittelbaren Heap anzeigen. Sie können dies bestätigen, indem Sie das eeheap -gc überprüfen. Dies sollte Ihnen zeigen, wo die Lautstärke steckt. Wenn mit allen oben genannten Befehlen keine Hinweise verfügbar sind, werden Ihre privaten Bytes normalerweise von nicht gesammelten Objekten in GC verwendet. Fahren Sie nun entweder mit gchandles oder gcleaks fort. Diese Befehle sollten Ihnen mitteilen, welche Typen / Objektadressen nicht zugeordnet werden können. Der Zeiger ist noch da, aber das Objekt ist weg. Dies ist ein solches kategorisches Problem für unveröffentlichte Ereignishandler.
G33kKahuna
10

Sie sollten nicht versuchen, Perfmon, Task-Manager oder ein ähnliches Tool zu verwenden, um Speicherlecks zu ermitteln. Sie sind gut, um Trends zu erkennen, aber sonst nicht viel. Die Zahlen, die sie in absoluten Zahlen angeben, sind zu vage und aggregiert, um für eine bestimmte Aufgabe wie die Erkennung von Speicherlecks nützlich zu sein.

Eine frühere Antwort auf diese Frage hat eine gute Erklärung für die verschiedenen Typen gegeben.

Sie fragen nach einer Toolempfehlung: Ich empfehle Memory Validator. Kann Anwendungen überwachen, die Milliarden von Speicherzuweisungen vornehmen.

http://www.softwareverify.com/cpp/memory/index.html

Haftungsausschluss: Ich habe Memory Validator entwickelt.

Stephen Kellett
quelle
1
Ich kann nicht einmal eine einfache Klassendatei (in Java) ausführen. Was gibt?
jn1kk
Ich vermute, dass Stephen und Devil irgendwie verwandt oder sogar geklont sind ...: D;)
Robert Koritnik
@ StephenKellett, Gibt es eine Testversion?
Pacerier
@Pacerier Wenn Sie dem Link folgen, gibt es eine Testversion für die x86- und x64-Versionen direkt über der Kaufoption auf der linken Seite.
Bradley A. Tetreault
10

Die Definition der Perfmon-Zähler wurde von Anfang an gebrochen und scheint aus irgendeinem Grund zu schwer zu korrigieren zu sein.

Einen guten Überblick über die Windows-Speicherverwaltung finden Sie im Video " Mysteries of Memory Management Revealed " auf MSDN: Es behandelt mehr Themen als zur Verfolgung von Speicherlecks erforderlich (z. B. Verwaltung von Arbeitssätzen), enthält jedoch genügend Details zu den relevanten Themen.


Um Ihnen einen Hinweis auf das Problem mit den Beschreibungen der Perfmon-Zähler zu geben, finden Sie hier die Insider-Informationen zu privaten Bytes aus "Leistungsindikator für private Bytes - Vorsicht! " Auf MSDN:

F: Wann ist ein privates Byte kein privates Byte?

A: Wenn es nicht ansässig ist.

Der Zähler für private Bytes meldet die Festschreibungsgebühr des Prozesses. Das heißt, die Menge an Speicherplatz, die in der Auslagerungsdatei zugewiesen wurde, um den Inhalt des privaten Speichers für den Fall zu speichern, dass er ausgelagert wird. Hinweis: Ich vermeide das Wort "reserviert", da möglicherweise eine Verwechslung mit dem virtuellen Speicher im reservierten Zustand vorliegt, der nicht festgeschrieben ist.


Von " Leistungsplanung " auf MSDN:

3.3 Private Bytes

3.3.1 Beschreibung

Privater Speicher ist definiert als Speicher, der einem Prozess zugewiesen ist, der nicht von anderen Prozessen gemeinsam genutzt werden kann. Dieser Speicher ist teurer als gemeinsam genutzter Speicher, wenn mehrere solcher Prozesse auf einem Computer ausgeführt werden. Der private Speicher in (traditionellen) nicht verwalteten DLLs besteht normalerweise aus C ++ - Statik und liegt in der Größenordnung von 5% des gesamten Arbeitssatzes der DLL.

Kennzeichen
quelle
1
Stimmen Sie ab wegen der wahnsinnig guten Beispiele dafür, wie es kaputt ist!
Bruno Brant
Das erste Zitat ist falsch. Für die Zuweisung von "Private Bytes" muss nichts "in der Auslagerungsdatei zugewiesen" sein (was eigentlich als Auslagerungsdatei bezeichnet wird). Sie müssen nicht einmal eine Auslagerungsdatei haben, damit "private Bytes" zugewiesen werden können. Tatsächlich verwendet nicht private Bytes Zuteilung nicht sofort jeden Raum überall , und verwenden Sie nicht immer kann so viel wie zugeordnet wurde.
Jamie Hanrahan
Das zweite Zitat ist nicht viel besser. Im DLL-Code verwendete private Bytes werden nicht unbedingt meist statisch innerhalb der DLL zugewiesen. DLL-Code kann problemlos VirtualAlloc, HeapAlloc (malloc und neu in der CRTL) usw. aufrufen. Außerdem wird versucht, die Größe des privaten Speichers als Prozentsatz der Größe des Arbeitssatzes zu beschreiben, was unsinnig ist. Ersteres hat eine virtuelle Größe (und ist für jede Verwendung des Codes mit derselben Eingabe gleich), während letzteres physisch ist (was sich von Lauf zu Lauf radikal unterscheiden kann, je nachdem, wie viel Speicher reich ist oder - verhungert ist die Maschine).
Jamie Hanrahan
5

Hier gibt es eine interessante Diskussion: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ Mein Verständnis dieses Threads ist, dass kleine Zuweisungen freigegeben werden nicht in privaten Bytes oder Arbeitssätzen wiedergegeben.

Um es kurz zu machen:

wenn ich anrufe

p=malloc(1000);
free(p);

dann spiegeln die privaten Bytes nur die Zuordnung wider, nicht die Freigabe.

wenn ich anrufe

p=malloc(>512k);
free(p);

dann spiegeln die privaten Bytes die Zuordnung und die Freigabe korrekt wider.

mcanti
quelle
7
Dies wird durch die Tatsache erklärt, dass die Speicherfunktionen der C-Standardbibliothek einen benutzerdefinierten oder Win32-Heap verwenden, bei dem es sich um einen Speicherverwaltungsmechanismus handelt, der über die Speicherverwaltung auf Prozessebene auf niedriger Ebene hinausgeht.
Kyberias
@ Kyberias, wie kommen wir darunter ?
Pacerier
während (1) frei (malloc (1000)); // Würde dies dazu führen, dass Private Bytes für immer zunehmen?
Franckspike
2
@franckspike: Nein, es wird bis zu einem bestimmten Punkt ansteigen (im Allgemeinen ca. 4 kB, dies kann jedoch variieren) und dann gestoppt werden, da die CRT zuvor freigegebenen Speicher wiederverwendet, anstatt neue Seiten vom Betriebssystem anzufordern.
Miral
@Pacerier: Sie können VirtualAlloc und VirtualFree aufrufen.
Jamie Hanrahan