neu und löschen [] sind schlechter als malloc und frei? (c ++ / VS2012)

9

OK, also habe ich Code geschrieben, um zu überprüfen, wie viel Speicher zur Laufzeit verfügbar ist. Eine ganze (minimale) CPP-Datei ist unter.

HINWEIS: Der Code ist nicht perfekt und nicht die beste Vorgehensweise, aber ich hoffe, dass Sie sich auf die Speicherverwaltung und nicht auf den Code konzentrieren können.

Was es tut (Teil I):

  • (1) Weisen Sie so viel Speicher wie möglich in einem zu Block. Löschen Sie diesen Speicher
  • (2) Ordnen Sie so viele mittelgroße Blöcke zu (16MB) wie möglich. Löschen Sie diesen Speicher.

- & gt; Das funktioniert gut

Was es tut (Teil II):

  • (1) Weisen Sie so viel Speicher wie möglich in einem Block zu. Löschen Sie diesen Speicher
  • (2) Ordnen Sie so viele kleine Blöcke (16kb) wie möglich zu. Löschen Sie diesen Speicher.

- & gt; Das verhält sich komisch!

Das Problem ist: Wenn ich das wiederhole, kann ich nur 522kb für die laufenden secons zuweisen --- & gt; ?

Es passiert nicht, wenn die zugewiesenen Blöcke z. 16 MB Größe.

Haben Sie irgendwelche Ideen, warum das passiert?

%Vor%

OUTPUT mit großen Speicherblöcken (das funktioniert gut)

%Vor%

OUTPUT mit kleinen Speicherblöcken (die Speicherzuweisung ist ab dem zweiten Lauf seltsam)

%Vor%

UPDATE:

Dies passiert auch mit neuen und lösch [] anstelle der internen Speicherzuweisung von STL.

UPDATE:

Es funktioniert für 64 Bit (ich habe den Speicher begrenzt, den beide Funktionen zu 12GB zuweisen können). Sehr seltsam. Hier ist ein Bild der RAM-Nutzung dieser Version:

UPDATE: Es funktioniert mit malloc und free, aber nicht mit new und delete [] (oder STL wie oben beschrieben)

    
S.H 26.08.2015, 14:07
quelle

2 Antworten

3

Wie ich bereits im obigen Kommentar erwähnt habe, handelt es sich höchstwahrscheinlich um ein Heap-Problem Fragmentierung . Der Heap verwaltet Listen von Blöcken unterschiedlicher Größe, um unterschiedliche Speicheranforderungen zu erfüllen. Größere Speicherblöcke werden für kleinere Speicheranfragen in kleinere Blöcke aufgeteilt, um zu vermeiden, dass der Unterschied zwischen der Chunk-Größe und der Anforderungsgröße verschwendet wird, was die Anzahl größerer Chunks reduziert. Wenn also ein größerer Chunk angefordert wird, verfügt der Heap möglicherweise nicht über genügend große Chunks, um die Anforderung zu erfüllen.

Fragmentierung ist ein Hauptproblem bei Heap-Implementierungen, da sie den nutzbaren Speicher effektiv reduziert. Einige Heap-Implementierungen können jedoch kleinere Chunks wieder in größere Chunks zusammenfügen und sind in der Lage, auch nach einer Anzahl kleinerer Anfragen größere Anforderungen zu erfüllen.

Ich habe Ihren obigen Code, sehr leicht modifiziert, mit% malloc ( ptmalloc ) von glibc ausgeführt und ich habe die folgenden Ergebnisse erhalten ...

%Vor%

Also scheint ptmalloc zumindest die Fragmentierung gut für dieses spezielle Szenario zu handhaben.

    
Jason 26.08.2015 16:59
quelle
1

Ich vermute, dass Sie aus irgendeinem Grund 32-Bit-Code ausführen?

Beste Schätzung: Ihre malloc -Implementierung hinterlässt Buchhaltungsdaten nach dem Freigeben überall im Speicher verstreut, wenn die Zuweisungen klein waren. Malloc-Implementierungen verwenden in der Regel unterschiedliche Zuweisungsstrategien für kleine und große Zuweisungen, so dass es nicht unangemessen ist, dass sich die Buchhaltungsinformationen an verschiedenen Stellen befinden.

Unter Unix werden kleine Zuweisungen normalerweise mit brk durchgeführt, während große Zuweisungen mit mmap(MAP_ANONYMOUS) erledigt werden. _tmain und stdafx.h bedeutet, dass Sie unter Windows testen, also IDK, wie dieses malloc unter der Haube funktioniert.

    
Peter Cordes 26.08.2015 14:19
quelle

Tags und Links