Wie kann ich die Heapfragmentierung in meinem C ++ - Programm erkennen und abschätzen?

8

Ich entwickle einen VC ++ NT-Dienst, der für viele Monate ununterbrochen arbeiten soll. Es verwendet VC ++ Runtime Heap intensiv. Offensichtlich kann die Heap-Fragmentierung zu irgendeinem Zeitpunkt eine Fehlfunktion verursachen (weil sie denkt, dass sie nicht genügend Speicher hat).

Welche Tests kann ich auf meinem Dienst ausführen, um den Grad der Fragmentierung des Heapspeichers zu schätzen?

    
sharptooth 19.10.2009, 14:16
quelle

6 Antworten

5

Sie haben ein paar Antworten erhalten, in denen Sie darüber sprechen, wie Sie Probleme bei der Heapfragmentierung vermeiden können, aber Ihre Frage wurde nicht direkt angesprochen. Fast der einzige Weg, abzuschätzen, wie wahrscheinlich es ist, dass es Probleme bei der Fragmentierung gibt, ist die Simulation von viel Nutzen und die Messung der Fragmentierung, die Sie erhalten.

Da es sich um einen NT-Dienst handelt, besteht die Simulation monatelanger Nutzung meist darin, viele Anfragen schnell zu stellen. Es ist sehr wahrscheinlich, dass Sie Anfragen schneller als erwartet stellen können, so dass Sie wahrscheinlich Anfragen für mehrere Monate in nur wenigen Stunden und möglicherweise sogar noch weniger simulieren können (abhängig von der Rate, mit der Sie normalerweise Anfragen erhalten) ).

Sobald Sie monatelange Arbeit simuliert haben (oder sogar während Sie dies tun), müssen Sie sich den Heap ansehen, um zu sehen, wie viel Fragmentierung Sie erhalten. Das ist nicht einfach, aber normalerweise ist es möglich. Du beginnst damit, einen Thread in den Service-Prozess zu injizieren (Googeln auf "Thread-Injektion" oder etwas auf dieser Bestellung sollte eine ziemlich große Menge an Informationen erhalten). Dann müssen Sie den Haufen laufen und (insbesondere) nach Blöcken suchen, die frei sind, aber zu klein, um die meisten Anforderungen zu erfüllen. Angenommen, Sie verwenden MS VC ++, führen Sie den Heap mit _heapwalk, und es wird durch den Heap laufen und Ihnen die Adresse, Größe und den Status (frei oder in Verwendung) jedes Blocks im Heap mitteilen.

Ein letztes Detail: Damit dies aussagekräftige Ergebnisse liefert, müssen sowohl die ausführbare UND-Datei als auch die DLL, die den injizierten Thread enthält, mit der Laufzeitbibliothek in einer DLL verknüpft werden. Das bedeutet, dass es für den gesamten Prozess einen Heap geben wird, sodass Ihr injizierter Thread den Heap durchlaufen wird, der von Ihrem Service verwendet wird. Wenn Sie die Standardbibliothek statisch verknüpfen, haben die DLL und der Dienst jeweils einen eigenen Heap. Die DLL wird ihren eigenen Heap durchlaufen, der Ihnen nichts über den Heap, der von dem Dienstprozess verwandt wird, erzählen wird.

    
Jerry Coffin 19.10.2009 15:17
quelle
2

Ich denke, der beste Weg wäre, einen eigenen Speichermanager zu schreiben (oder einen zu kaufen), der diese Daten anbietet. Jeder andere Weg würde den Heap selbst ändern und somit das Ergebnis ungültig machen.

Eine Strategie, die einfacher zu implementieren ist, ist die Zuweisung von Speicherblöcken unterschiedlicher Größe und das Warten auf einen Fehler - aber ich denke nicht, dass das ein guter Weg ist. Wie auch immer - je größer die Blockgröße, desto weniger die Fragmentierung. Aber abhängig vom Speichermanager kann die Zuweisung des Blocks das Ergebnis ändern.

Bearbeiten: Ich habe einen Link zum Brammenverteiler (thx für den Kommentar) gefunden, der die Statistik zeigt. Es ist aber in Deutsch und die englische Version des Artikels enthält nicht so viele Informationen. Verwenden Sie Babelfish für die Übersetzung.

Ссылка ( babelfish version )

Ссылка

    
Tobias Langner 19.10.2009 14:23
quelle
1

Wenn Sie den Heap für niedrige Fragmentierung für Windows einschalten, können Sie die Aufgabe auf älteren Systemen ausführen. auf neuen Systemen ist der Standard eingeschaltet (Vista, Server 2008)

%Vor%

Es gibt ein Tool VMMap von sysinternals (jetzt Microsoft), das einen guten Überblick gibt die Speicherfragmentierung.

    
Totonga 20.10.2009 07:34
quelle
1

Der einfachste Weg, die Fragmentierung zu erkennen, ist, Ihre größte Zuteilung, die Ihr Programm jemals vornehmen wird, zu ermitteln und dann immer wieder mindestens den doppelten Betrag zuzuweisen. Wenn die Zuweisung fehlschlägt, d. h. NULL UND Ihre Heap-Verwendung wie vom Code bestimmt zurückgegeben wird - so etwas unter Windows

%Vor%

ist weniger als ein bestimmter Prozentsatz des Systemspeichers, normalerweise 75%, dann haben Sie definitiv ein Fragmentierungsproblem.

    
chizel 20.06.2012 10:21
quelle
0

Ich stimme Tobias zu - einen eigenen Speichermanager zu haben ist eine hervorragende Möglichkeit, dies zu tun. Ich kenne nur ein paar Entwickler, denen ich vertrauen würde, um diese Art von Code zu schreiben, obwohl ...

Eine andere Möglichkeit besteht darin, Ihre Objekte ab und zu selbst zu sammeln oder zu konsolidieren - bei geringen Lasten ... dh Ihr Dienst kann für eine Weile inaktiv sein, während er den Speicher "defragmentiert", aber ich Ich bin mir nicht sicher, ob Sie das gewünschte Verhalten ohne eigenes Speichermanagement garantieren können.

    
Tim 19.10.2009 14:38
quelle
0

Ich bin mir sicher, dass es Tools für Windows gibt, die Ihnen den Status eines Speichers geben können, aber trotzdem sollten Sie Ihren Service mit diesem Problem entwickeln.

Zuerst sollten Sie verstehen, welche Zuweisungen Sie vornehmen. Ich denke, der einfache Weg besteht darin, die neuen Operatoren und die Delete-Operatoren zu überschreiben, und von diesen neuen Operatoren sollten Sie einige Statistiken Ihrer Zuordnungen zählen und dann die Standardoperatoren new und delete Ihres Compilers aufrufen.

Die Mindeststatistik, die Sie meiner Meinung nach zählen sollten, ist die Anzahl der Zuweisungen von gemeinsamen Blockgrößenbereichen.

z.B. Blöcke zwischen 0 Bytes bis 15 Bytes, Blöcke zwischen 16 Bytes bis 32 Bytes, Blöcke zwischen 32 Bytes bis 48 Bytes, ...

Sie können auch die Anzahl der sequentiellen Zuweisung für jeden Blockgrößenbereich hinzufügen

Nachdem Sie diese Daten gesammelt haben, können Sie das Fragmentierungsproblem reduzieren, indem Sie Blöcke auf gängige Größen ausrichten .

Die beste und einfachste Technik für die Ausrichtung ist die Verwendung von Blöcken mit der Potenz 2.

Um beispielsweise eine Zahl an die nächste Zahl anzupassen, die durch 16 geteilt wird, können Sie die folgende Funktion verwenden:

%Vor%

Natürlich sollten Sie Ihre Statistiken verwenden, um die beste Potenz von 2 für die Ausrichtung auszuwählen. Ziel ist es, eine Zahl zu erreichen, die die meisten Ihrer Zuweisungen in wenigen Blöcken erreichen, und gleichzeitig den Aufwand für die Ausrichtung angemessen zu halten.

Viel Glück ...

    
Barak C 19.10.2009 15:28
quelle

Tags und Links