Referenz auf temporäre Spielobjekte

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2367
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Referenz auf temporäre Spielobjekte

Beitrag von Jonathan »

MasterQ32 hat geschrieben:Man könnte ja auch dann eine Art Objekt-Referenz machen, welche ein ID-System mit Hashmap nutzt, dass die De-/Referenzierung via Hashmap+ID übernimmt. Wenn man dann *, -> überschreibt, sollte das ja doch relativ fix gehen (gucken ob ID in hashmap/array/whatever, wenn nicht, nullptr)
Dadurch hätte man eine schöne sharedpointerfreie geschichte
Wenn ich gedanklich überschlage, was man alles tun muss um eine Hasmap zu implementieren, kann ich mir nicht vorstellen, dass das weniger Aufwand ist als ein shared/weak ptr. Tatsächlich müsste man schon wirklich Glück haben, die selbe Geschwindigkeit zu erreichen, ich würde eher davon ausgehen, dass es um einiges langsamer ist.
Begründung: Man braucht eine ganze Reihe Buckets um die Zeiger zu speichern. Entweder hat man sehr viele, die dann fast alle leer sind, oder man riskiert das man nach dem Hashen noch den Bucket durchiterieren muss. Was ein weak_ptr letztendlich macht ist direkt auf den passenden Speicherbereich zuzugreifen (anstatt die Position erst über Hashen eines Wertes zu ermitteln) und dort eine Operation auszuführen (anstatt potentiell den ganzen Bucket durchzuloopen). Gut, man muss im extra-Speicher zwei Zähler anstatt einen Zeiger speichern (wobei es ja in den meisten Fällen gar keine 32-bit Zähler sein müssen), aber dafür hat die Hashmap immer eine Menge Buckets, von denen viele leer sein können. Oder, was noch schlimmer ist, die Buckets sind keine Arrays sondern Listen, wodurch Speicherplatz gespart wird, aber der Zugriff noch langsamer wird.

Hashmap sind von der Idee nett, weil sie fast sowas wie konstante Zugriffszeit bieten, aber das bedeutet ja noch lange nicht, dass diese Konstante in der Praxis nicht groß sein kann.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: Referenz auf temporäre Spielobjekte

Beitrag von xq »

Richtig, aber sagen wir mal wir nehmen 260 000 Buckets. Das wäre dann 1 MB Ram, Komplett verkraftbar, wir können unsere IDs fröhlich verteilt vergeben ohne eine hohe Chance auf Kollision. Ich sagte auch nicht, dass es schneller ist, aber es kommt definitiv mit weniger Allokationen aus als eine Sharedpointer geschichte und man hält auch keinen toten speicher, sondern eben nur das konstante hashmap array

Sind ja auch alles nur so Ideen ;)
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

Re: Referenz auf temporäre Spielobjekte

Beitrag von Spiele Programmierer »

Das Problem ist, dass die Buckets nicht der Reihe nach gefüllt werden und es schnell erste Kollisionen gibt.
Zu bedenken ist außerdem, dass ein Zugriff in eine Hashmap konzeptbedingt eigentlich immer erstmal mit nahezu hundertprozentiger Wahrscheinlichkeit ein Cachemiss ist.
Außerdem habe ich gehört, dass insbesondere die Hashmaps aus der STL scheinbar in der Praxis relativ ineffizient sein sollen, weil sie im Hintergrund mit Buckets arbeiten, die die Situation noch verschlimmern.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2367
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Referenz auf temporäre Spielobjekte

Beitrag von Jonathan »

Ich habe es jetzt übrigens mit den shared_ / weak_pointern implementiert. Soweit bin ich echt sehr zufrieden, die Umstellung war nicht all zu komplex und man kann bei der Benutzung wirklich wenig falsch machen. Ich musste nur einige Funktionen anpassen, damit mein SceneManager wirklich nur weak_ptr und nicht normale Pointer auf Entities rausgibt, aber nachdem das getan war und alle Benutzer angepasst waren funktionierte alles tadellos. Und jetzt kann ich jederzeit bedenkenlos alles löschen, was mir nicht mehr gefällt, und brauche keine Angst vor irgendwelchen Abstürzen mehr zu haben.
Am Besten gefällt mir übrigens, dass man nicht nur auf sichere Art prüfen kann, ob eine Referenz gültig ist, sondern es auch tun muss. An einer Stelle habe ich mich kurz darüber geärgert, weil ich mir sicher war, dass sie hier eigentlich immer gültig sein muss, aber dann ist mir aufgefallen, dass es theoretisch doch nicht ganz so sicher ist. Solche Bugs, die Ewigkeiten nicht in Erscheinung treten und selbst wenn sau schwer zu debuggen sind, weil man sie kaum rekonstruieren kann, schon zu fixen bevor sie auftreten, ist wirklich ein gutes Gefühl :) Das sind dann einfach die Momente, in denen ich C++ liebe, weil man darin einfach so unglaublich robust programmieren kann, wenn man es denn richtig macht :D
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Antworten