Defragmentierung von C ++ Heap Allocator & STL

8

Ich möchte einen selbst defragmentierenden Speichermanager schreiben, wobei ein einfacher inkrementierender Heap-Allokator in Kombination mit einem einfachen komprimierenden Defragmentierer verwendet wird.

Das grobe Schema würde sein, Blöcke beginnend bei der niedrigsten Speicheradresse, die nach oben geht, zuzuordnen und die Buchhaltungsinformation beginnend bei der höchsten Speicheradresse, die nach unten arbeitet, zu halten.

Der Speichermanager würde intelligente Zeiger zurückgeben - die intrusive_ptrs von boost scheinen für die buchhaltenden Strukturen am offensichtlichsten zu sein, die dann selbst auf den tatsächlichen Speicherblock zeigen und somit eine Ebene der Indirektion geben, so dass die Blöcke leicht bewegt werden können.

Der Defragmentierer würde den Heap von "Generierungs" -Bookmarks herunter komprimieren, um den Prozess zu beschleunigen und nur eine bestimmte Menge an Speicher gleichzeitig zu defragmentieren. Raw-Zeiger auf die Blöcke selbst wären bis zum nächsten Defrag-Durchlauf gültig und könnten daher frei herumgereicht werden, bis die Leistung verbessert wird.

Die spezielle Anwendung dafür ist die Konsolenspielprogrammierung und so konnte am Anfang oder Ende jedes Frames ein Defrag-Durchlauf relativ sicher durchgeführt werden.

Also meine Frage ist, hat jemand diese Art von Zuordnungsschema in Kombination mit STL verwendet, würde es STL ganz einfach auseinander blasen, wie ich vermute. Ich kann std :: list & lt; intrusive_ptr & gt; Arbeiten auf der intrusive_ptr-Ebene, aber was ist mit der Zuweisung der stl-Liste Knoten selbst gibt es sowieso die nächsten / prev Zeiger als intrusive_ptr selbst zu überschreiben oder werde ich nur eine Standard-Heap-Allokator neben dieser dynamischeren haben müssen.

    
user176168 20.09.2009, 12:14
quelle

5 Antworten

5

Wenn Sie Objekte im Speicher verschieben möchten, können Sie dies nicht vollständig tun. Sie können dies nur mit Objekten tun, die wissen , dass sie möglicherweise verschoben werden. Sie benötigen auch einen Verriegelungsmechanismus. Wenn eine Funktion für ein Objekt aufgerufen wird, kann sie nicht verschoben werden.

Der Grund dafür ist, dass das gesamte C ++ - Modell auf Objekten basiert, die an festen Punkten im Speicher sitzen. Wenn also ein Thread eine Methode für ein Objekt aufruft, dieser Thread pausiert und das Objekt verschoben wird, würde ein Desaster auftreten, wenn der Thread fortgesetzt wird.

Jedes Objekt, das einen rohen Speicherzeiger auf ein anderes Objekt enthielt, das verschoben werden könnte (einschließlich eines Unterobjekts von sich selbst), würde nicht funktionieren.

Ein solches Speichermanagement kann funktionieren, aber Sie müssen sehr vorsichtig sein. Sie müssen bei der Implementierung von Handles und der Semantik der Handle- & gt; -Pointer-Sperre streng sein.

Bei STL-Containern können Sie den Zuordner anpassen, er muss jedoch weiterhin feste Raw-Speicherzeiger zurückgeben. Sie können keine Adresse zurückgeben, die verschoben werden könnte. Aus diesem Grund müssen Sie, wenn Sie STL-Container verwenden, Container mit Handles sein, und die Knoten selbst sind normaler dynamisch zugeordneter Speicher. Sie können feststellen, dass Sie zu viel in Overhead in der Handle-Indirektion und immer noch Probleme in der Fragmentierung der Handle-Auflistungen haben, als Sie mithilfe von STL gewinnen.

Die Verwendung von Containern, die Ihre Handles direkt verstehen, ist möglicherweise der einzige Weg nach vorn, und selbst dann kann es immer noch viel Overhead im Vergleich zu einer C ++ - Anwendung geben, die traditionelle Objekte im Speicher verwendet.

    
Charles Bailey 20.09.2009, 13:03
quelle
0

STL-Container werden mit nackten Zeigern implementiert.

Sie können einen benutzerdefinierten Zuordner angeben, wenn Sie sie instanziieren (also initialisieren sie ihre Zeiger mit Ihrem Zuordner), aber da die zugewiesenen Werte in nackten Zeigern gespeichert sind, wissen Sie nicht, wo diese Zeiger sind und damit Sie kann sie später nicht ändern.

Stattdessen könnten Sie eine Teilmenge der STL selbst implementieren: Ihre Versionen der STL-Container könnten dann mit verwalteten Zeigern implementiert werden.

    
ChrisW 20.09.2009 12:50
quelle
0

Eine alternative Technik, die ziemlich gut bekannt ist, ist das Buddy-System . Sie sollten sich das für zusätzliche Inspiration ansehen.

    
EvilTeach 20.09.2009 16:23
quelle
0

Wenn dies für die Konsolenspielprogrammierung vorgesehen ist, ist es viel einfacher, zur Laufzeit freie Speicherzuweisungen zu sperren. Und zur Startzeit, aber das ist ein bisschen schwierig zu erreichen.

    
MSN 20.09.2009 23:46
quelle
0

Wenn ich mich vor der Fragmentierung fürchte, heißt das, dass Sie mit Datenstücken jonglieren, die einen großen Teil Ihres Gedächtnisses ausmachen, und allein durch diese Tugend können Sie nicht viele davon haben. Weißt du schon, was das sein wird? Vielleicht wäre es besser, ein Level herunter zu setzen und spezifischere Entscheidungen zu treffen, was den anderen Code und die allgemeine Leistung Ihrer Anwendung weniger beeinträchtigt.

Eine Liste ist ein außergewöhnlich schlechtes Beispiel, das in einen defragmentierenden Speichermanager eingefügt werden kann, da es sich, wie die meisten anderen STL-Datenstrukturen, um einen Haufen winziger Stücke handelt. Wenn Sie dies tun, wird es alle Arten von offensichtlichen negativen Auswirkungen haben - einschließlich der Leistung Ihres Defragmentierers, auch die indirekten Kosten etc. Die einzigen Strukturen, wo es Sinn macht IMO sind Contigious - Array, Deque, Hauptteil der Hashtabelle Diese Dinge, und nur jenseits einer bestimmten Größe, und erst dann, wenn sie nicht mehr in der Größe verändert werden. Diese Art von Dingen, wieder, für spezifische Lösungen, anstatt generische.

Kommentiere zurück, wie alles ausgeht.

    
3yE 14.11.2009 13:30
quelle