C++ - Organisation/Verwaltung von millionen Objekten
Verfasst: 12.04.2017, 19:51
Hallo.
Mein Projekt verfügt über ein Hauptobjekt Welt. Diese Welt hat eine oder mehrere Karten. In den Karten gibt es Objekte. Objekte können weitere Objekte beinhalten, z.B. wenn das Objekt ein Behälter (Kiste, Beutel, Truhe, usw.) ist.
Die "Haupthierarchie" ist daher sehr einfach, wie vermutlich bei den meisten Programmen, die eine Welt/Spielwelt darstellen möchten: Welt -> Karte/Level -> Objekt -> Objekt -> usw..
Ein Objekt verfügt direkt nur über die Eigenschaften/Attribute, die zu 99% in allen Objekten vorkommen, wie z.B. Größe (XYZ) und Gewicht (gramm). Alle weiteren Informationen, Definitionen und Beschreibungen werden dem Objekt direkt zugeordnet, bzw. verfügt das Objekt über Möglichkeiten, diese Informationen zu speichern. Es gibt zwar Basisobjekte, die in erster Linie dazu dienen ein Objekt zu erzeugen, aber in der Regel halten die Objekte die meisten Informationen nochmal/redundant. Durch diese Redundanz kann ich z.B. zwei Objekte durch das gleiche Basisobjekt erstellen, aber danach individuell anpassen. Ich hatte anfangs versucht, diese Redundanz zu vermeiden, indem ich z.B. bestimmte Daten erst "verdopple" wenn ich sie anpassen möchte, aber das hat die ganze Sache extrem verkompliziert und war letzten Endes nicht schneller, verbrauchte nur weniger Speicher.
Die Objekte und dazugehörigen Daten/Informationen werden alle durch einen Speichermanager erzeugt und verwaltet. Jede Klasse hat einen Verweis/Zeiger/Weakpointer auf die Welt, wo der Speichermanager "liegt". Fällt der Referenzzähler auf 0, wird eine Delete-Funktion aufgerufen, diese ruft dann die entsprechende Freigabefunktion/Free von der Welt auf. Die Freigabefunktion führt den Destruktor von der freizugebenden Instanz aus und erledigt die weiteren Arbeiten, um den Speicher freizugeben.
Diese Vorgehensweise macht die ganze Angelegenheit extrem schnell, ich teste das immer mit den Daten der Spieleklassiker Ultima 7 und Serpent Isle. (https://www.gog.com/game/ultima_7_complete)
Für Ultima 7 werden beim Laden der Spielwelt 3.361.485 Klassen/Instanzen erstellt und miteinander verknüpft. Bei Serpent Isle sind es 3.956.333 Klassen/Instanzen. In beiden Fällen ist die gesamte Welt in wenigen Sekunden geladen. Das Objekt-System ist noch in der Entwicklung und ich gehe davon aus, dass in der finalen Version über 5.000.000 Klassen/Instanzen erstellt werden.
Das verwendete System ist zwar extrem schnell, hat aber auch seine Nachteile, wie z.B. dass der Speichermanager und die Welt/Karte/Objekte nicht threadsafe sind. Ich muss, sobald ich Daten lesen/ändern/erstellen/freigeben möchte, die Welt sperren (CriticalSection).
Ich kann mir aber auch nicht vorstellen, dass es Programme mit vielen Daten gibt, die multithreaded sind, aber die Daten ohne einen zentralen Sperrmechanismus bearbeiten. Ich habe das zwar nicht getestet, aber ich gehe davon aus, dass wenn ich z.B. die Daten und Speichermanager threadsafe mache, die Performance hart in den Keller geht.
Habt ihr eine Idee wie ich das besser lösen könnte?
Mein Projekt verfügt über ein Hauptobjekt Welt. Diese Welt hat eine oder mehrere Karten. In den Karten gibt es Objekte. Objekte können weitere Objekte beinhalten, z.B. wenn das Objekt ein Behälter (Kiste, Beutel, Truhe, usw.) ist.
Die "Haupthierarchie" ist daher sehr einfach, wie vermutlich bei den meisten Programmen, die eine Welt/Spielwelt darstellen möchten: Welt -> Karte/Level -> Objekt -> Objekt -> usw..
Ein Objekt verfügt direkt nur über die Eigenschaften/Attribute, die zu 99% in allen Objekten vorkommen, wie z.B. Größe (XYZ) und Gewicht (gramm). Alle weiteren Informationen, Definitionen und Beschreibungen werden dem Objekt direkt zugeordnet, bzw. verfügt das Objekt über Möglichkeiten, diese Informationen zu speichern. Es gibt zwar Basisobjekte, die in erster Linie dazu dienen ein Objekt zu erzeugen, aber in der Regel halten die Objekte die meisten Informationen nochmal/redundant. Durch diese Redundanz kann ich z.B. zwei Objekte durch das gleiche Basisobjekt erstellen, aber danach individuell anpassen. Ich hatte anfangs versucht, diese Redundanz zu vermeiden, indem ich z.B. bestimmte Daten erst "verdopple" wenn ich sie anpassen möchte, aber das hat die ganze Sache extrem verkompliziert und war letzten Endes nicht schneller, verbrauchte nur weniger Speicher.
Die Objekte und dazugehörigen Daten/Informationen werden alle durch einen Speichermanager erzeugt und verwaltet. Jede Klasse hat einen Verweis/Zeiger/Weakpointer auf die Welt, wo der Speichermanager "liegt". Fällt der Referenzzähler auf 0, wird eine Delete-Funktion aufgerufen, diese ruft dann die entsprechende Freigabefunktion/Free von der Welt auf. Die Freigabefunktion führt den Destruktor von der freizugebenden Instanz aus und erledigt die weiteren Arbeiten, um den Speicher freizugeben.
Diese Vorgehensweise macht die ganze Angelegenheit extrem schnell, ich teste das immer mit den Daten der Spieleklassiker Ultima 7 und Serpent Isle. (https://www.gog.com/game/ultima_7_complete)
Für Ultima 7 werden beim Laden der Spielwelt 3.361.485 Klassen/Instanzen erstellt und miteinander verknüpft. Bei Serpent Isle sind es 3.956.333 Klassen/Instanzen. In beiden Fällen ist die gesamte Welt in wenigen Sekunden geladen. Das Objekt-System ist noch in der Entwicklung und ich gehe davon aus, dass in der finalen Version über 5.000.000 Klassen/Instanzen erstellt werden.
Das verwendete System ist zwar extrem schnell, hat aber auch seine Nachteile, wie z.B. dass der Speichermanager und die Welt/Karte/Objekte nicht threadsafe sind. Ich muss, sobald ich Daten lesen/ändern/erstellen/freigeben möchte, die Welt sperren (CriticalSection).
Ich kann mir aber auch nicht vorstellen, dass es Programme mit vielen Daten gibt, die multithreaded sind, aber die Daten ohne einen zentralen Sperrmechanismus bearbeiten. Ich habe das zwar nicht getestet, aber ich gehe davon aus, dass wenn ich z.B. die Daten und Speichermanager threadsafe mache, die Performance hart in den Keller geht.
Habt ihr eine Idee wie ich das besser lösen könnte?