Warum Index-Handles in C und C++ die besseren Pointer sind
Handles are the better pointers (2018)
Nach 15 Jahren Arbeit mit großen C++-Codebasen, in denen Smart Pointer für zehntausende kleine Objekte sorgen, plädiert der Autor für einen anderen Weg: Speicherverwaltung in zentrale Systeme verlagern, Objekte gleichen Typs in Arrays bündeln und nach außen nur Index-Handles statt roher Pointer geben. Das reduziert Cache-Misses, verhindert Speicherfragmentierung und macht Use-after-Free früh erkennbar – vorausgesetzt, die Architektur ist datenorientiert statt klassisch objektorientiert.
Ohne den Basiszeiger zur Berechnung des Speicherorts eines Elements kann der Code außerhalb des Systems selbst mit viel krimineller Energie nicht auf den Speicher des Elements zugreifen.
- boricj
Das ist im Grunde das, was ich bei der Arbeit in meinem Embedded-Projekt gemacht habe. Objekt-Pools mit Indizes und Generationen. Sehr, sehr viel einfacher, als mit rohen Pointern herumzupfuschen, günstiger als shared_ptr/weak_ptr und kein Aufräumen nötig, wenn man Dinge löscht, weil die gespeicherte Generation nicht zur Generation des neuen Objekts passt. Man kann das sogar default-konstruierbar machen, wenn man die Generation auch bei der Instanziierung hochzählt (sodass nur gerade Generationen lebendig sind) und das Ganze hinter High-Level-Abstraktionen mit C++ verstecken. Allerdings stammt mein Wissen über diese Techniken aus Videospiel-Architekturen der 2000er, da Spiele wie GTA: Vice City dafür bekannt sind, sie zu verwenden.
- nickwanninger
Meine Doktorarbeit handelt von diesem Thema, und ich hatte vor ein paar Jahren einen ASPLOS-Paper über Handle-basierte Speicherunterstützung in nicht verwalteten Sprachen (C/C++) über LLVM: https://nickw.io/papers/asplos24-alaska.pdf
Der Overhead, den wir dort gesehen haben, kommt überraschenderweise allein vom Instruktions- und Branch-Overhead durch die Verwendung von Software-Handles – ich arbeite derzeit daran, das in Hardware umzusetzen, und die Overheads sind dann viel geringer.
- Conscat
Ich habe einen echten Versuch unternommen, in meinem C++-Projekt auf diese Weise zu programmieren (größtenteils wegen dieses Artikels), und persönlich fand ich es extrem umständlich, weil man den Besitzer dieser Ressource überallhin mitnehmen muss, wo man das Handle verwenden will. Das selbst kann die Performance verschlechtern, wenn es in verschiedenen Funktionen liegt, es machte generische Programmierung schwierig und solcher Code muss stärker template-lastig sein, und es war schwierig zu refaktorieren.
Aber das war ein sehr Low-Level-Projekt, und ich vermute, Floooh dachte wohl eher an Endnutzer-Anwendungen.