Speicherverwaltung für cpp

Ich versuche derzeit eine performancekritische anwendung in bezug auf laufzeit zu optimieren. Im kritischen Bereich werden in einer doppelloop jede menge objekte erzeugt. ich denke, dass die new's und deletes relativ teuer sind. daher würde ich gern new und delete überladen, sodass diese nicht jedes mal speicher reservieren, sondern stadessen vorallocierten speicher aus einem singleton-memorypool bekommen. ich denke, das ist die sauberste lösung, die den eigentlichen programmcode nicht unnötig gruselig macht.

Mein Problem:
ich hab keine ahnung, wie genau man new und delete implementieren sollte, damit alles sauber läuft. hat sowas schonmal jemand gemacht und kann mir nen paar tips geben, wie man das ordentlich löst, bzw ob es überhaupt einen gewaltigen perfomancegewinn bringt?

edit:
die klasse, die später den delete aufruft behandelt das objekt mit dem typen der oberklasse. ist delete standardmäßig virtual, oder wird dort dann der standardoperator aufgerufen?
 
das standard-new ist bei kleinen objekten nicht sehr effizient, da es vor den eigentlichen daten immer noch ein kleinen bereich des speichers für kontrolldaten (zur steuerung von delete) reserviert. Ich habe das mal ausprobiert und ein einzelnes int hat 28 statt 4 byte Speicher verbraucht. Ein Memory-pool ist also wohl genau das richtige für dich (wobei du für jede klasse einen eigenen benötigen wirst.
Jede Menge Beispiele findest du bei Google: http://www.google.de/search?hl=de&q=c+++memory+pool&btnG=Google-Suche&meta=
 
Danke erstmal für die Hilfe.
Da bleibt erstmal nurnoch die Frage nach dem delete offen. Da ich auf den code der betroffenen Klassen keinen einfluss habe, kann ich die überladung nur realisieren, indem ich von den klassen ableite. das problem ist, dass der delete wiederum in einer externen funktion (auf die ich auch keinen einfluss habe) aufgerufen wird. das würde also bedeuten, dass der delete der oberklasse virtual sein muss, damit das delete der abgeleiteten klasse aufgerufen wird. Die Frage ist, ob die standardoperatoren implizit virtual sind. Wenn das nicht der Fall sein sollte, müsste ich eine globale überladung von new machen, was ich eigentlich nicht möchte, da somit das gesamte programm davon betroffen wäre. oder gibt's da noch einen trick, um den scope einer globalen überladung zu reduzieren?
 
der Globale new-operator ruft immer "operator new" der klasse auf (um speicher zu bekommen), falls diese diesen überlädt. Ansonsten müsstest du, wie gesagt, von der Klasse ableiten und da die Operatoren überladen. Falls aber der Destruktor der Basisklasse nicht virtuell ist, wirst du damit nicht weit kommen.
Es gibt allerdings noch eine andere Möglichkeit, die sich Placement-new nennt:
Hierbei bist du dafür verantwortlich, speicher bereitzustellen, und das placement-new konstruiert dann in diesem Speicher ein objekt (kümmert sich allerdings nicht mehr um die speicheranforderung, da das dann ja deine aufgabe ist)

Code:
// angenommen, du hast einen pointer "buffer" auf ein freies speicherstück (z.B. auf die entsprechende stelle deines memory-pools
char* buffer = new char[10000] // freier speicher 
Objekt* obj1 = new (buffer) Objekt("param1", 2, param3); // es wird an der Stelle "buffer" ein objekt konstruiert
Objekt* obj2 = new (buffer+100) Objekt("hallo"); // 100 byte(chars) weiter noch eins


beispiele/erklärungen gibts bei google eine menge, z.B. hier noch ein beispiel: http://dotnet-snippets.de/dns/placement-new-SID807.aspx
 
Code:
#include <iostream>

class A
{
};

class B:public A
{
public: 
	void operator delete(void* mem)
	{
		std::cout<<"class B"<<std::endl;
	}
};

int main()
{
	A* a= new B();
	delete a;
	system("pause");
}

OK, dieser kleine test hat mir verraten, dass das mit dem delete wohl nicht klappen wird. Der Compiler verbietet sogar delete virtual zu machen.

Hat zufällig noch jemand ne Idee, wie man da dennoch memory-pooling machen könnte? Ich denk mal so ziemlich alles crasht, sobald die lib den delete macht.
 
was spricht denn gegen placement new?

Code:
class BoeseUnveraenderbareKlasse {};

char* mempool = new char[10000];
BoeseUnveraenderbareKlasse* ptr = new (mempool) BoeseUnveraenderbareKlasse();

// und zum löschen den destruktor explizit aufrufen
ptr->~BoeseUnveraenderbareKlasse()

mit delete gehts natürlich nicht, denn der overhead, den new erstellt, um delete die arbeit zu erleichtern, fällt ja weg und deshalb weiß delete nun nicht mehr, was es tun soll.
 
na gut, dann gehts wohl wirklich nicht.
und den globelen operator new überladen würde ich auch nicht. Mehr Möglichkeiten fallen mir jetzt aber auch nicht ein....
 
Hab mir schon gedacht, dass das nen schwieriges Problem ist. Hab jetzt was gebastelt, womit die Daten asynchron vorgeladen werden und somit mit hoher wahrscheinlichkeit schon vorhanden sind, wenn sie gebraucht werden. Hab damit ne ganz akzeptable performance zustandebekommen.
 
Zurück
Oben