Warum ist rtti so langsam?
-
hustbaer schrieb:
dot schrieb:
GorbGorb schrieb:
Ich habe nicht vor eine dynamic_cast oder typeid Orgie anzurichten, keine Sorge.
Es ist aber sehr wahrscheinlich, dass du gerade dabei bist, dir basierend auf
typeideinfach nur eine Artdynamic_castzu basteln, auch wenns auf den ersten Blick vielleicht nicht direkt danach aussieht...Wobei dynamic_cast auch nicht unbedingt schneller sein wird als typeid()...
Normalerweise dürfte sogar eher das Gegenteil der Fall sein, da
dynamic_castdie komplette Hierarchie beachten muss...
Aber darum gehts mir auch nicht. Mir geht's darum, dasstypeidunddynamic_castmeist Sympton eines Designproblems sind. Es wäre also sinnvoll, zumindest mal zu reflektieren, was man da eigentlich gerade zu tun gedenkt, anstatt mit dem Kopf durch die Wand zu laufen.
-
Ich will component based design umsetzen, d.h. ich brauche eine Klasse "entity" die beliebige Komponententypen aufnehmen kann (und twar nicht immer die gleichen).
Das könnte ich jetzt so machen, dass etwas baue wieentity< ComponentA , ComponentB , ComponentC >. Das wird aber dann nicht mehr funktionieren, wenn ich zur Laufzeit neue entity "Arten" erstellen will (z.B. weil ich eine Datei einlese, in der festgelegt ist, welche components zu einer entity gehören). Und dazu brauche ich rtti. Das wird nur im framework verwendet, in der Logik für mein Programm brauche ich es nicht.
-
Wo genau brauchst du dabei RTTI für was genau?

-
Ich übergebe diese entity einem entity_system, das Komponenten in Abhängigkeit von ihrem Typ an spezielle container weitergibt:
entity -> entity_system -> (über virtuelle Funktion) -> meta_entity_system<...> (kennt den Typ der folgenden container) -> container< ComponentType* >
entity_system weiß noch nicht, für welche Typen es container gibt. Dadurch muss ich nicht alles, das entity_system verwendet, neu compilen, wenn ich einen neuen Komponententyp einbaue.
In meta_entity_system muss ich dann aber wissen, welche Komponententypen in der entity stecken, also brauche ich rtti.
-
Nurmal rein prinzipiell: Wie kann deine Anwendung was mit einer zur Compiletime der Anwendung unbekannten Schnittstelle anfangen?
Edit: Ok, es könnte eine neue Komponente was mit einer neuen Schnittstellen anfangen. RTTI wäre da theoretisch eine Lösung, wird praktisch aber schon rein auf technischer Ebene nicht unproblematisch sein, da die Typen, mit denen du es da zu tun hast, wohl aus verschiedenen dlls stammen müssen. Fakt ist, dass Code nur Schnittstellen verwenden kann, die zur Compiletime bekannt sind. Ich denk, dass es da eine bessere Lösung geben muss. Ich frag mich eben grad, was genau der Sinn davon ist, die Komponenten zentral zu verwalten, wenn es doch offenbar an zentraler Stelle nicht genug Information dafür geben kann.
-
Zumal Zentralisierung der grundlegenden Idee des komponentenbasierten Designs völlig zuwiderläuft. Man will da doch eigentlich erreichen, dass die Komponenten ihre jeweilige Implementation untereinander überhaupt nicht kennen müssen. Auch sehe ich nicht, wie du Komponenten in Klassen quetschen willst, wenn CBSE sich von Objektorientierung genau dadurch abgrenzt, dass eine Schnittstelle auch von etwas anderem als Objekten getragen werden kann (wie Funktionen, Sockets oder was auch immer).
Geht es dir um eine Art Framework zur Verwaltung von Metadaten, d.h. Abhängigkeitsauflösung zur Laufzeit? Das wäre vorstellbar, aber dafür solltest du keine Typidentifikation zur Laufzeit brauchen. Das ginge wahrscheinlich sogar ohne virtuelle Methoden.
-
Es geht mir nicht primär um dlls, sondern darum dass ich code nicht ständig neu compilen will. Vielleicht kams nicht ganz so klar rüber: Ich kenne die Typen aller Komponenten beim compilen, aber nicht alle Kombinationen (naja, rein theoretisch wäre das schon möglich, aber ich bezweifle, dass es sinnvoll ist, beim compilen schon alles mit allem zu kombinieren, weil das ziemlich schnell sehr viele Möglichkeiten werden).
@seldon: Irgendwo muss ich meiner entity sagen, welche Komponenten zu ihr gehören. Danach werden die Komponenten dann aber auf getrennte container aufgeteilt. Da Komponenten bei mir allein aus Daten bestehen und von mehreren subsystems für jeweils einen bestimmten Komponententyp bearbeitet werden, weiß ich auch nicht, was du mit Schnittstellen genau meinst.
-
Wahrscheinlich reden wir gerade völlig aneinander vorbei. Ich rede hiervon.
So richtig klar ist mir nicht, was du unter "componend based design" verstehst; wenn Komponenten bei dir bloß Daten sind, ist es jedenfalls nicht das, was ich meinte. Kannst du vielleicht etwas genauer beschreiben, was du eigentlich erreichen willst?
-
Ok stimmt, ich meine was anderes:
-> http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/Im Grunde geht es darum, dass man statt mit einer Klassenhierarchie mit aus mehreren Komponenten zusammengesetzten Objekten (entities) arbeitet. Eine entity ist nur eine einzigartie id, der mehrere Komponenten zugeordnet sind.
Die Komponenten werden dann seperat voneinder gespeichert. Da Komponenten nur aus Daten bestehen werden sie von einem bestimmten subsystem bearbeitet. Wie aus dem Artikel hervorgeht, wird das bei der Spieleprogrammierung verwendet.
Als Beispiel könnte etwa eine entity einen Baum im Spiel repräsentieren. Die entity hätte dann eine RenderComponent, eine PhysicsComponent, DestructibleComponent, ...
Es gäbe ein RenderSystem, das alle RenderComponents abarbeitet, ein PhysicsSystem für die Physik etc.
Der Vorteil ist, dass man damit verschiedene Aspekte trennen kann, statt sie in einem großen god object zu verwursteln. Abgesehen von weniger schmutzigem code kann man so leichter multi threaden und nutzt den cache durch seperate Speicherung der Komponenten besser.
-
Hmm...okay, da muss ich jetzt ein bisschen vorsichtig sein, weil ich keinerlei Erfahrung mit solchen Systemen habe. Wenn ich den Artikel richtig verstehe, ist das Ganze eine höchst dynamische Angelegenheit, bei der die Betrachtung von Entities als Typen relativ wenig Sinn ergibt - er schreibt ja ziemlich ausführlich darüber, dass man eher an relationelle Datenbanken denken sollte. So wie ich das lese, kann sich beispielsweise zur Laufzeit ändern, welche Komponenten eine Entität beinhaltet (Beispiel: Ein Techniker kommt vorbeigestiefelt und dübelt eine neue Kanone an dein Motorrad).
Er hat ja auch Code dazu - eine Entity (der Schlüssel) ist da ein int, eine Komponente ein Array von floats (die Daten), und das System (der eigentliche Code) befasst sich dann mit der Verarbeitung. Komponenten in eine Klasse zu gießen ergibt für mein Verständnis da noch Sinn, obwohl das Interface im Wesentlichen auf eine Methode der Form "gib mir Wert X, wenn du ihn hast" hinausliefe, und um den globalen Kontext zu vermeiden, wäre eine Abstraktion für die Datenbank(verbindung) bzw. dessen, was ihre Rolle übernimmt, vermutlich sinnvoll, aber die Entity selbst, so schreibt er ja ausdrücklich, sollte die Daten nicht verwalten.
Aber wie gesagt, das alles schreibe ich unter dem Vorbehalt, dass mein Verständnis des Feldes sich auf das Lesen dieses Artikels beschränkt.
-
Kannst du hiermit leben?
int type_count = 0; template<class T> int get_id(){ static int id = type_count++; return id; } class Base{ public: virtual int id()const=0; }; class Derived : public Base{ public: virtual int id()const{ // Kann man auch per Base<Derived> template erzeugen lassen return get_id<Derived>(); } }; template<class T> T*my_downcast(Base*b){ if(b.id() == get_id<T>()) return static_cast<Derived*>(b); else return 0; }Eventuell kann man auch irgendwie direkt die Methodenzeiger vergleichen und sich so den virtuellen Aufruf sparen, aber den Syntax kriege ich nicht aus dem Stegreif hin.
-
Ich habe auch nicht vor seine Definition 1:1 zu übernehmen, ich bin ja nur Hobbyprogrammierer und brauche kein so generisches framework. Bei mir wird jeder Komponententyp zur compile Zeit festgelegt sein. Sie können beliebige Daten enthalten (also nicht nur floats). Ich habe auch nicht vor irgendwas großartig abzuspeichern, von daher ist mir der Punkt mit den Datenbanken ziemlich egal. Meine entity hat nur die Funktion
template< class Type > Type *component()die - wenn möglich - einen Pointer auf die zugehörige Komponente zurückgibt. Zur Zeit managed die entity auch den Speicher für Komponenten, das will ich bei Gelegenheit noch ändern, um Komponenten getrennt voneinander in vector-like containern aufzubewahren. So langsam will ich aber dazu kommen was Handfestes zu schreiben, wenn die performance nicht reicht kann ich ja immernoch nachbessern.