Objekttyp in C++ zur Laufzeit ermitteln

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Objekttyp in C++ zur Laufzeit ermitteln

Beitrag von Schrompf »

Goderion hat geschrieben:Jedes Objekt kümmert sich dann um die eigene Löschung, was einen virtuellen Destruktor überflüssig macht.
Am Anfang hat mich das etwas genervt, für jedes Objekt extra eine Delete-Funktion zu implementieren.
Aber im Nachhinein hat sich das als extrem nützlich erwiesen, vor allem in Kombination mit einem eigenen Speichermanager.
Aua aua aua. Sorry, aber das ist so falsch, dass ich gar nicht weiß, wie ich das erklären soll. Du erfindest also den Destruktor neu, nur halt manuell. Du hast keine Garantien für nix, keinen Compiler-Support, aber nen eigenen Heap, den Du mit nem Custom Allocator auch kriegen könntest. Und hast Du Deinen eigenen Heap denn jemals profiled? Weißt Du überhaupt, ob er tatsächlich schneller ist? Immerhin trittst Du gegen eines der am besten getesteten und optimierten Code-Teile der CRT an.

Nuja, mach, wie Du magst. Aber das Ganze riecht doch heftig nach Not Invented Here.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Goderion
Beiträge: 82
Registriert: 16.09.2012, 12:02

Re: Objekttyp in C++ zur Laufzeit ermitteln

Beitrag von Goderion »

Krishty hat geschrieben:Hast du globale Optimierungen (LTCG) aktiviert, so dass das Konstruktorverhalten bekannt ist? Visual C++ kapituliert oft vor Zeigern; wenn du es als lokale Variable erzeugst, funktioniert es aber manchmal.
Vielen Dank für den Tip, habe LTCG mal aktiviert. Es läuft jetzt etwas schneller, aber der vtable wird immer noch genutzt, NARF!
Schrompf hat geschrieben:Aua aua aua. Sorry, aber das ist so falsch, dass ich gar nicht weiß, wie ich das erklären soll. Du erfindest also den Destruktor neu, nur halt manuell.
Ich versehe dich nicht so richtig, glaub ich. Wieso erfinde ich den Destruktor neu? Die Objekte haben weiterhin ihre Destruktoren, die auch aufgerufen werden.
Schrompf hat geschrieben:Du hast keine Garantien für nix, keinen Compiler-Support, aber nen eigenen Heap, den Du mit nem Custom Allocator auch kriegen könntest.
Was für Garantien? Was für Compiler-Support?
Ich bin mir nicht sicher, ob ein Custom Allocator meinen Speichermanager ersetzen kann, bzw. es sind mehrere Speichermanager.
Schrompf hat geschrieben:Und hast Du Deinen eigenen Heap denn jemals profiled? Weißt Du überhaupt, ob er tatsächlich schneller ist? Immerhin trittst Du gegen eines der am besten getesteten und optimierten Code-Teile der CRT an.
Ich habe das mal mit 1.000.000 Objekten getestet (new und delete).
Mit Speichermanager:
9947 µs
9819 µs
9917 µs
9930 µs
Ohne:
65394 µs
65708 µs
65360 µs
65385 µs

Es geht auch nicht nur um die Performance, durch den Speichermanager kann ich immer gut sehen, was im Speicher gerade los ist. Beim Testen finde ich das extrem hilfreich.
Schrompf hat geschrieben:Nuja, mach, wie Du magst. Aber das Ganze riecht doch heftig nach Not Invented Here.
Wonach es auch immer riechen mag, es läuft extrem stabil und sicher. ;-)

EDIT:
Ich habe jetzt auch mal die Performance vom shared_ptr mit meiner Lösung verglichen.
Test zum shared_ptr:

Code: Alles auswählen

	for (int i = 0; i < 1000; ++i)
	{
		std::shared_ptr<ClassTest> P[1000];

		for (int j = 0; j < 1000; ++j)
		{
			P[j] = std::make_shared<ClassTest>();
		}

		for (int x = 0; x < 100; ++x)
		{
			std::shared_ptr<ClassTest> PP[1000];

			for (int j = 0; j < 1000; ++j)
			{
				PP[j] = P[j];
			}
		}
	}
Ergebnis:
1949918 µs
1942421 µs
1940712 µs
1940622 µs

Test zum OLE-Style:

Code: Alles auswählen

	for (UInt32 i = 0; i < 1000; ++i)
	{
		spObject P[1000];

		for (UInt32 j = 0; j < 1000; ++j)
		{
			P[j] = new ClassTest();
		}

		for (UInt32 x = 0; x < 100; ++x)
		{
			spObject PP[1000];

			for (UInt32 j = 0; j < 1000; ++j)
			{
				PP[j] = P[j];
			}
		}
	}
Ergebnis:
1015445 µs
1017010 µs
1018666 µs
1015513 µs

Der shared_ptr ist zu meiner Überraschung langsamer, liegt vielleicht daran, dass der shared_ptr auch einen "Weak-Counter" hat.
Gene
Beiträge: 25
Registriert: 22.05.2003, 11:26

Re: Objekttyp in C++ zur Laufzeit ermitteln

Beitrag von Gene »

Goderion hat geschrieben: Der shared_ptr ist zu meiner Überraschung langsamer, liegt vielleicht daran, dass der shared_ptr auch einen "Weak-Counter" hat.
Ich tippe auf thread sicherheit.Der std::shared_ptr ist thread sicher, das heißt mehrere threads können "zeitgleich" kopien erstellen und der reference count wird korrekt angepasst. Deine Lösung ist nicht Thread sicher.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Objekttyp in C++ zur Laufzeit ermitteln

Beitrag von Schrompf »

Die selbe Vermutung habe ich auch beim Heap. Gegenüber dem generischen Heap kann man eigentlich nur mit Kontextwissen bei speziellen Anwendungsfällen was rausholen. Dazu sind Custom Allocators ja da, nöch :-)

Aber nuja, jeder wie er mag.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Objekttyp in C++ zur Laufzeit ermitteln

Beitrag von Krishty »

Naja; der generische Heap wird auch durch andere Sachen ausgebremst – Prüfdaten gegen Heap Overflow Attacks und so. Stimmt aber schon; HeapAlloc() sollte meist unter 100 Takten liegen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Goderion
Beiträge: 82
Registriert: 16.09.2012, 12:02

Re: Objekttyp in C++ zur Laufzeit ermitteln

Beitrag von Goderion »

Gene hat geschrieben:
Goderion hat geschrieben: Der shared_ptr ist zu meiner Überraschung langsamer, liegt vielleicht daran, dass der shared_ptr auch einen "Weak-Counter" hat.
Ich tippe auf thread sicherheit.Der std::shared_ptr ist thread sicher, das heißt mehrere threads können "zeitgleich" kopien erstellen und der reference count wird korrekt angepasst. Deine Lösung ist nicht Thread sicher.
Jo, das scheint es gewesen zu sein. Benutze ich die thread sichere Version, ist der shared_ptr etwas schneller, was wohl an den fehlenden virtual calls liegt.
2206904 µs
2206011 µs
2202900 µs
2205281 µs

Bei mir laufen 5 Threads (Main, Input, Video, Sound und Logik), aber ich brauche an nur sehr wenigen Stellen thread sichere Objekte.
Schrompf hat geschrieben:Die selbe Vermutung habe ich auch beim Heap. Gegenüber dem generischen Heap kann man eigentlich nur mit Kontextwissen bei speziellen Anwendungsfällen was rausholen. Dazu sind Custom Allocators ja da, nöch :-)
Mein Speichermanager ist nicht thread sicher, was natürlich einer der Gründe sein wird, warum ich damit schneller Objekte/Speicher reservieren und wieder freigeben kann. An den Stellen, wo ich den Speichermanager nutze, ist auch keine thread-Sicherheit nötig.
Schrompf hat geschrieben:Aber nuja, jeder wie er mag.
Immer so ein Abschlusssatz... ;-)
Nur weil ich nicht immer den aktuellen Standard nutze, bedeutet das nicht, dass es gleich Kagge ist. Die Unreal Engine nutzt z.B. auch keine std::shared_ptr.
Ich will jetzt die Unreal-Engine nicht mit meinem Programm vergleichen oder das Können der Unreal-Entwickler mit meinen Fähigkeiten, das wäre absurd,
aber nur weil etwas nicht dem Standard entspricht, es gleich zu verteufeln, halte ich für falsch.

Ich überlege auch schon seit gestern, ob und wo ich den std::shared_ptr in meinem Programm sinnvoll einsetzen kann, habe auch schon etwas mit dem shared_ptr experimentiert,
aber aktuell sehe ich ihn ihm keinen Nutzen für mich, vielleicht unter anderen Bedingungen in einem anderen Programm.

Ich bedanke mich für die Antworten und Hinweise, die ihr mir gegeben habt und werde weiter darüber nachdenken.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Objekttyp in C++ zur Laufzeit ermitteln

Beitrag von Schrompf »

Goderion hat geschrieben:Ich bedanke mich für die Antworten und Hinweise, die ihr mir gegeben habt und werde weiter darüber nachdenken.
Nur zur Klarstellung, damit das nicht falsch stehen bleibt: Ich finde es Mist, was Du da baust. Aber das ist nur meine persönliche Meinung. Wenn Du Dir Deiner Sache sicher bist, dann muss Dich das nicht stören. Du kannst in Deinem eigenen Code machen, was Du willst. Mehr sollen meine Nachsätze nicht sagen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Antworten