Ich war daran interessiert, für jedes Subsystem ein Profil zu erstellen und einen verwalteten Speicherpool zu führen, damit ich eine Statistik darüber erhalten konnte, wie viel Speicher in so etwas wie Sounds oder Grafiken verwendet wurde. Was wäre jedoch ein Design, das dafür funktioniert? Ich dachte daran, mehrere Allokatoren und nur einen pro Subsystem zu verwenden, was jedoch zu globalen Variablen für meine Allokatoren führen würde (oder so scheint es mir). Ein anderer Ansatz, den ich gesehen habe / der vorgeschlagen wurde, besteht darin, einfach neu zu überladen und einen Allokator für einen Parameter zu übergeben.
Ich hatte eine ähnliche Frage über auf Stackoverflow hier mit einer Prämie, aber es scheint , als ob vielleicht war ich zu ungenau oder einfach nur da ist nicht genug , um Menschen mit Wissen in dem Thema.
Antworten:
Es ist definitiv eine Frage, die für manche vage klingen könnte;)
Aber ich glaube ich weiß woher du kommst.
Sie haben eine Million Möglichkeiten, wie Sie dies implementieren möchten. Einige dieser Entscheidungen sollten sich sowohl auf die Zielplattformen als auch auf die allgemeinen Entwurfsziele beziehen. Diese Überlegungen lösen alle Bindungen, bis Sie sich mit unterschiedlichen Implementierungskosten wohl genug fühlen, um das Design von der Plattform und den allgemeinen Designproblemen zuerst zu erweitern. Bis dahin gibt es hier einige Möglichkeiten, die Sie nicht in Bezug auf Komplexität (Verwaltungsaufwand) oder den Umgang mit Entfernung oder Änderungen kosten, wenn Sie Ihre Meinung ändern ...
Wenn das Ziel darin besteht, zu messen und zuzuweisen, mit der Möglichkeit, Pools zu verwenden, müssen Sie zuerst über den Mindestsatz an lebenswertem Code nachdenken, um loszulegen. Zur Erklärung können Sie, wenn Sie Teil von Klassen sind, eine Klasse erstellen, die für einen Heap steht, oder stattdessen eine Reihe von Funktionen verwenden, die ein Handle oder einen Heap-Namen annehmen. Es ist wirklich eine Frage der Semantik, um ehrlich zu sein. Die nächste Entscheidung ist neu oder malloc; Ich bin ein Teil von Malloc, weil ich mich oft mit Konstrukten auf niedriger Ebene beschäftige und in den meisten Implementierungen weiß, dass New Malloc aufruft, und ich muss mir keine Sorgen über die Komplexität der Überladung neuer und über alle Plattformen machen . Ich habe jedoch oft Systeme oder Komponenten gebaut, um neue zu überladen oder zu haken. Und natürlich ist das Kernproblem oder der Unterschied, dass "neu" muss den Typ vor der Zuweisung kennen, wobei 'malloc' keine Rolle spielt und Sie mit malloc nach der Zuweisung in einen Typ auflösen. All dieses Detail soll Ihnen eine Idee und einen Kontext geben, in dem Sie Designentscheidungen in diesen Angelegenheiten treffen können :)
Also werde ich Klasse und Malloc auswählen, weil es hier einfacher zu erklären ist, aber es ist am Ende wirklich egal. Die Einbauten weisen im Vergleich zum Rest des Gesamtdesigns nur geringe Materialunterschiede auf.
In dieser Hypothese weiß ich also, dass ich (oder davon ausgehen werde) möglicherweise 7-8 echte Instanziierungen von Subsystemklassen habe und Hunderttausende von Anrufen für die Zuweisung und kostenlos vorwegnehme. Da sich ein Großteil meiner Neugier und meiner wirklichen Dynamik bei all dem auf die Größe und die Profilseite bezieht, möchte ich die Leistung der App nicht belasten. Für den Anfang könnte ich mich entscheiden, das Ganze einfach offen und öffentlich zu lassen, bis ich es festgenagelt habe, während ich es im gesamten Rest der App implementiere. Eine Struktur wird dies gut tun. Das 's_' soll zeigen, welche Variablen eindeutig für Statistiken bestimmt sind.
Das ist extremLeichtgewicht an vielen Fronten und vielleicht ein guter Ort, um zu konkretisieren, wo immer Sie wirklich hin wollten. Und Sie haben sofort ein Problem, woher wissen Sie die Größe des freigegebenen Artikels. (Dies wäre ein Problem, das für fast jeden Ansatz zu lösen ist.) Da dies ein Spielforum ist, können Sie die ersten paar Bytes mit der Größe dotieren, oder Sie müssen entweder umbrechen oder sich auf andere Weise daran erinnern. Die meisten Spielentwickler sollten nicht zu sehr gegen Doping sein, und es ist das einfachste Beispiel, wenn man bedenkt, dass ich bereits eine Textwand erstellt habe. Grundsätzlich geht das so: Sie wollen nicht, ob geholfen werden kann, die inhärente Ausrichtung zu zerstören, Sie wollen wissen, da fast kostenlos, ob die Größe kohärent ist. Also etwas so Einfaches wie "s_allocs ++; s_total + = size; uint64 * p = (uint64 *) malloc / calloc (size + = 8); * p = 0xDEADDAED00000000 | Größe; return p + 1; "wobei die Zuweisungen weniger als 4 GB betragen und uint64 das ist, was der Compiler für ein 64-Bit-Int ohne Vorzeichen hält, und wo Sie den Sanity-Wert kostenlos überprüfen können.
Dies ist alles eine Möglichkeit, um Ihnen das Nötigste zu minimalen Kosten zu bieten, die den Anforderungen entsprechen. Das tut es nichtAdresszuweisung von Klassen mit virtuellen Funktionen, wenn diese für die Profilerstellung oder Verwaltung vorgesehen sind, da Sie die Größe der von Ihnen verwendeten C ++ - Umgebung nicht vorhersehen können, ohne sie zu überladen oder neu zu verknüpfen, oder wenn Sie sich auf den Konstruktor in einem der Klassen verlassen seltsame Wege, die von keiner anderen 'init'-Funktion gehandhabt werden konnten. Andernfalls ist eine Struktur eine Klasse, eine willkürliche Zuordnung und beim Casting alle gleich. Wenn Sie an Neuem interessiert sind und die inhärente virtuelle Tabellen- oder Konstruktorsemantik benötigen, müssen Sie Neu einbinden, aber das ist ein ganz anderes Tier, das Sie wirklich studieren müssen, um sicherzustellen, dass Sie die neuen Anforderungen erfüllen und signalisieren müssen Ihr Code, der neu behandelt, auf welchen Bucket dies angewendet wurde. Ansonsten ist das obige Konzept dasselbe.
Noch wichtiger ist, dass dies Ihr Gehirn in Schwung bringt und hoffentlich in die Richtung geht, die Sie brauchen und was Ihre Toleranzen sind, nachdem Sie etwas mehr hinter dem Vorhang gesehen haben. Es gibt keinen Assistenten :)
quelle
Sie müssen für diese Daten nichts in Ihrem Spiel implementieren. Tools wie Massif Valgrind können alle erforderlichen Daten aus den Debug-Symbolen extrahieren. Sie können die Speicherauszüge von Massif in Massif Visualizer anzeigen .
quelle
Ich empfehle dringend, keinen eigenen Speicherzuweiser zu schreiben. Sie benötigen eine stabile, zuverlässige und getestete Version mit guten Debugging-Funktionen wie Korruptionserkennung und vor allem: zuverlässigen Statistiken. Dies ist keine leichte Aufgabe und hat viele Fallstricke. Es gibt großartige und einfach zu verwendende, zum Beispiel:
Doug Lea Allokator
Es kommt mit dem Konzept der Speicherplätze, Sie können einen pro Subsystem verwenden. Es ist hoch optimiert und bietet Ihnen großartige Statistiken und Laufzeitinformationen.
quelle