zeckensack
2002-07-03, 13:36:39
Nachdem mir hier (http://www.forum-3dcenter.org/vbulletin/showthread.php?hreadid=24822) so schön geholfen wurde, bekommt ihr jetzt was zurück:
Einen ultraprimitiven 'Hunk' (Name inspiriert von Q3), der dynamisch 64 Byte große, perfekt alignete Speicherhappen verwalten kann.
Der Konstruktor bekommt als Parameter die maximal zu erwartende Speicherbelegung (diese wird auf die nächste 4k-Grenze aufgerundet). Dieser Speicher wird unterteilt in 4kB große 'blocks' (Bezeichnung aus dem Code), diese sind wiederum unterteilt in 'chunks' (dies sind die 64 Byte großen Häppchen). Es gibt zwei Verwaltungsstrukturen:
Hunk::block ist ein Array und speichert für jeden 'block'
1)Den Zeiger auf den vom System angeforderten Speicher
2)Die korrekt alignete Version dieses Zeigers
3)64 einzelne bits, die die Belegung der einzelnen 'chunks' speichern
Hunk::usage ist ein Bitfeld, daß für jeden 'block' genau ein Bit speichert. Ist der Block komplett voll, ist dieses Bit gesetzt, ist auch nur ein 'chunk' frei, ist das Bit leer. Auf diese Weise kann der Allokator schnell einen 'block' finden, in dem noch mindestens ein 'chunk' frei ist.
Dann gibt's noch den 'victim_cache'. Hier sind ein paar 'chunks' gespeichert, die nicht mehr verwendet werden. Sinn: der Allokator muß normalerweise einen Block mit mindestens einem freien Chunk suchen, dann einen Chunk auswählen und ein bisserl die Zeiger jonglieren. Der Victim-Cache vereinfacht diese Prozedur, was bei ständigem allocate/free potentiell deutlich schneller ist.
Einschränkung: Man kann nur Speicherhäppchen mit genau 64 Byte Größe auf den Hunk schmeißen. Das dafür sehr effizient. Sieht man auch daran, daß die 'wichtigen' Funktionen "allocate64" und "free64" heißen. Könnte man erweitern, war aber für meine Zwecke (noch) nicht notwendig.
Suppi: Die Speicherzuweisung (auf der System-Seite) erfolgt 'just in time', ie erst dann, wenn sie wirklich nötig wird. Freigegeben wird der Speicher erst dann, wenn der Hunk selbst wieder zerstört wird. Dadurch wird nur minimale Zeit in der Speicherverwaltung des Betriebssystems verbracht (was bei Windows eine ziemlich gute Idee ist ...).
Die Verwaltungsstrukturen summieren sich auf einen konstanten Overhead von 193 bit pro verwaltetem 4k-Block, respektive 6176 Byte pro verwaltetem MB, also 0,6%.
Dieser Speicher wird direkt bei der Initialisierung komplett abgegriffen.
Einen ultraprimitiven 'Hunk' (Name inspiriert von Q3), der dynamisch 64 Byte große, perfekt alignete Speicherhappen verwalten kann.
Der Konstruktor bekommt als Parameter die maximal zu erwartende Speicherbelegung (diese wird auf die nächste 4k-Grenze aufgerundet). Dieser Speicher wird unterteilt in 4kB große 'blocks' (Bezeichnung aus dem Code), diese sind wiederum unterteilt in 'chunks' (dies sind die 64 Byte großen Häppchen). Es gibt zwei Verwaltungsstrukturen:
Hunk::block ist ein Array und speichert für jeden 'block'
1)Den Zeiger auf den vom System angeforderten Speicher
2)Die korrekt alignete Version dieses Zeigers
3)64 einzelne bits, die die Belegung der einzelnen 'chunks' speichern
Hunk::usage ist ein Bitfeld, daß für jeden 'block' genau ein Bit speichert. Ist der Block komplett voll, ist dieses Bit gesetzt, ist auch nur ein 'chunk' frei, ist das Bit leer. Auf diese Weise kann der Allokator schnell einen 'block' finden, in dem noch mindestens ein 'chunk' frei ist.
Dann gibt's noch den 'victim_cache'. Hier sind ein paar 'chunks' gespeichert, die nicht mehr verwendet werden. Sinn: der Allokator muß normalerweise einen Block mit mindestens einem freien Chunk suchen, dann einen Chunk auswählen und ein bisserl die Zeiger jonglieren. Der Victim-Cache vereinfacht diese Prozedur, was bei ständigem allocate/free potentiell deutlich schneller ist.
Einschränkung: Man kann nur Speicherhäppchen mit genau 64 Byte Größe auf den Hunk schmeißen. Das dafür sehr effizient. Sieht man auch daran, daß die 'wichtigen' Funktionen "allocate64" und "free64" heißen. Könnte man erweitern, war aber für meine Zwecke (noch) nicht notwendig.
Suppi: Die Speicherzuweisung (auf der System-Seite) erfolgt 'just in time', ie erst dann, wenn sie wirklich nötig wird. Freigegeben wird der Speicher erst dann, wenn der Hunk selbst wieder zerstört wird. Dadurch wird nur minimale Zeit in der Speicherverwaltung des Betriebssystems verbracht (was bei Windows eine ziemlich gute Idee ist ...).
Die Verwaltungsstrukturen summieren sich auf einen konstanten Overhead von 193 bit pro verwaltetem 4k-Block, respektive 6176 Byte pro verwaltetem MB, also 0,6%.
Dieser Speicher wird direkt bei der Initialisierung komplett abgegriffen.