Wenn Sie eine speicherintensive Anwendung in C ++ unter Windows entwickeln, können Sie Ihren eigenen benutzerdefinierten Speichermanager schreiben, um Speicher aus virtuellem Adressraum zuzuweisen, oder ermöglicht Ihnen CRT die Kontrolle und die Speicherverwaltung für Sie? Ich bin besonders besorgt über die Fragmentierung, die durch die Zuweisung und Freigabe kleiner Objekte auf dem Heap verursacht wird. Aus diesem Grund denke ich, dass der Speicher nicht mehr ausreicht, obwohl genügend Speicher vorhanden ist, aber fragmentiert ist.
Ich denke, Ihre beste Lösung ist es, keine zu implementieren, bis Profile beweisen , dass die CRT Speicher so fragmentiert, dass die Leistung Ihrer Anwendung beeinträchtigt wird. CRT-, Core-OS- und STL-Leute verbringen viel Zeit damit, über Speicherverwaltung nachzudenken.
Es besteht eine gute Chance, dass Ihr Code unter den vorhandenen Zuordnern sehr gut funktioniert, ohne dass Änderungen erforderlich sind. Das ist sicherlich eine bessere Chance, als wenn Sie beim ersten Mal gleich einen Speicherzuordner bekommen. Ich habe schon vorher Speicherzuweiser für ähnliche Umstände geschrieben, und es ist eine monströse Aufgabe, die ich übernehmen muss. Nicht so überraschend, die Version, die ich geerbt hatte, war voller Fragmentierungsprobleme.
Der andere Vorteil des Wartens, bis ein Profil zeigt, dass es ein Problem ist, ist, dass Sie auch wissen, ob Sie tatsächlich etwas behoben haben. Das ist der wichtigste Teil eines Performance-Fixes.
Solange Sie Standard-Auflistungsklassen und einen Algorithmus (wie STL / BOOST) verwenden, sollte es nicht sehr schwierig sein, später im Zyklus einen neuen Zuordner zu installieren, um die Teile Ihrer Codebasis zu reparieren, die dies tun muss repariert werden. Es ist sehr unwahrscheinlich, dass Sie einen handcodierten Zuordner für Ihr gesamtes Programm benötigen.
Obwohl die meisten von Ihnen angeben, dass Sie keinen eigenen Speichermanager schreiben sollten, könnte es immer noch nützlich sein, wenn:
Wenn Sie Ihren eigenen Speichermanager schreiben möchten, müssen Sie ihn in die folgenden 4 Teile aufteilen:
Wenn diese vier Teile klar getrennt sind, wird es auch leicht, ein Teil durch ein anderes zu ersetzen oder ein neues Teil hinzuzufügen, z.B.:
Nachdem ich selbst einen Speichermanager geschrieben habe, kann ich nur darauf hinweisen, dass es sehr praktisch ist, einen eigenen Speichermanager einfach zu erweitern. Z.B. Was ich regelmäßig tun muss, ist Speicherlecks in lang laufenden Serveranwendungen zu finden. Mit meinem eigenen Speichermanager mache ich das so:
Obwohl Sie ähnliche Funktionen mit vorgefertigten Komponenten ausführen können, haben sie einige Nachteile:
Aber versuchen Sie auch, realistisch zu sein: Wenn Sie kein Problem mit Speicherfragmentierung, Performance, Speicherlecks oder Speicherüberschreibungen haben, gibt es keinen wirklichen Grund, einen eigenen Speichermanager zu schreiben.
Aus meiner Erfahrung ist die Fragmentierung meistens ein Problem, wenn Sie fortlaufend große Puffer (wie über 16k) zuweisen und freigeben, da diese diejenigen sind, die letzten Endes zu wenig Speicher zur Verfügung stellen kann keinen großen Platz für einen von ihnen finden.
In diesem Fall sollten nur diese Objekte eine spezielle Speicherverwaltung haben, den Rest einfach halten. Sie können die Wiederverwendung von Puffern verwenden, wenn sie immer die gleiche Größe haben, oder komplexeres Speicherpooling, wenn sie in der Größe variieren.
Die Standard-Heap-Implementierungen sollten kein Problem haben, einen Platz für kleinere Puffer zwischen vorherigen Zuordnungen zu finden.
Sie entscheiden sich, Ihren eigenen benutzerdefinierten Speichermanager zu schreiben, um Speicher aus virtuellem Adressraum zuzuweisen oder erlauben Sie CRT, die Kontrolle zu übernehmen und die Speicherverwaltung für Sie vorzunehmen?
Die Standardbibliothek ist oft gut genug. Wenn dies nicht der Fall ist, besteht ein kleinerer Schritt darin, operator new
und operator delete
für bestimmte Klassen und nicht für alle Klassen zu überschreiben, anstatt sie zu ersetzen.
Es hängt sehr stark von Ihren Speicherzuordnungsmustern ab. Aus meiner persönlichen Erfahrung heraus gibt es in der Regel ein oder zwei Klassen in einem Projekt, die besondere Aspekte bei der Speicherverwaltung erfordern, da sie häufig in dem Teil des Codes verwendet werden, in dem Sie viel Zeit verbringen. Es kann auch Klassen geben, die in einem bestimmten Kontext eine spezielle Behandlung benötigen, aber in anderen Kontexten verwendet werden können, ohne sich darum zu kümmern.
Ich verwalte oft diese Art von Objekten in einem std :: vector oder etwas Ähnliches und Explizites, anstatt die Zuordnungsroutinen für die Klasse zu überschreiben. In vielen Situationen ist der Heap wirklich übertrieben und die Zuweisungsmuster sind so vorhersagbar, dass Sie nicht auf dem Heap reservieren müssen, sondern in einer viel einfacheren Struktur, die größere Seiten aus dem Heap reserviert, die weniger Verwaltungsaufwand haben als jede einzelne Instanz der Haufen.
Dies sind einige allgemeine Dinge, über die Sie nachdenken sollten:
Zuerst sollten kleine Objekte, die schnell zugewiesen und zerstört wurden, auf den Stapel gelegt werden. Die schnellste Zuordnung sind diejenigen, die nie gemacht werden. Die Stapelzuordnung erfolgt ebenfalls ohne Sperren eines globalen Heapspeichers, was gut für Multi-Thread-Code ist. Die Zuweisung auf dem Heap in c / c ++ kann im Vergleich zu GC-Sprachen wie Java relativ teuer sein, also versuchen Sie es zu vermeiden, es sei denn, Sie benötigen es.
Wenn Sie viel zuweisen, sollten Sie auf die Threading-Performance achten. Ein klassischer Fallstrick sind String-Klassen, die dazu neigen, dem Benutzer viele Zuweisungen zu verbergen. Wenn Sie viele Threads in mehreren Threads verarbeiten, werden sie möglicherweise mit einem Mutex im Heap-Code kämpfen. Zu diesem Zweck kann die Kontrolle über die Speicherverwaltung die Dinge erheblich beschleunigen. Der Wechsel zu einer anderen Heap-Implementierung ist hier im Allgemeinen nicht die Lösung, da der Heap weiterhin global ist und Ihre Threads dagegen ankämpfen werden. Ich denke, Google hat einen Heap, der allerdings in Multithread-Umgebungen schneller sein sollte. Habe es nicht selbst ausprobiert.
Tags und Links optimization c++ windows memory-management