Heap-Fragmentierung (Pascal)

Heap-Fragmentierung (Pascal)

Beitragvon zatzen » Mi 8. Mär 2017, 17:34

Hallo!

Lange Zeit war das kein Thema für mich, aber in letzter Zeit ist es mir bewusst geworden:
Wenn man in Pascal mit GetMem und FreeMem hantiert, dann kann es schnell passieren,
dass der Heap fragmentiert wird, und obwohl insgesamt z.B. 64K noch frei wären, lässt
sich dieser Speicherplatz dann nicht mehr am Stück nutzen.

Dieses Problem stellt sich mir nun inbesondere aufgrund der Überlegung, ob ich für ZSM
noch einen Tracker schreibe. Den brauche ich nicht unbedingt, ich kann von einem anderen
Tracker konvertieren, aber es wäre auch so ein kleiner Wunsch der in Erfüllung gehen würde.

Nun hätte ich dabei aber das Problem, wenn man Samples reinlädt und der User sich
zwischendurch entscheidet, diese durch andere auszutauschen. Der Heap würde
fragmentiert werden.

Hat jemand einen Ansatz, wie man das vermeiden könnte?
Es wäre nämlich auch für ein Spiel praktikabel, wenn man für verschiedene Levels
unterschiedliche Grafik, Musik und Sounds laden möchte.

Ich erinnere mich, dass DOSferatu einen Speichermanager geschrieben hatte, der
zu Anfang den gesamten verfügbaren Speicher reserviert und dann selbst organisiert.
Vielleicht wäre das schon die Lösung.
Ich habe mich damit nur nicht länger befasst weil mir der Speicherumgang mit
GetMem und FreeMem so vertraut war und ich bisher keine Probleme mit
Heap-Fragmentierung hatte.
Benutzeravatar
zatzen
617K-Frei-Haber
 
Beiträge: 310
Registriert: Di 17. Apr 2012, 04:10
Wohnort: bei Köln

Re: Heap-Fragmentierung (Pascal)

Beitragvon DOSferatu » Mo 13. Mär 2017, 19:03

zatzen hat geschrieben:Ich erinnere mich, dass DOSferatu einen Speichermanager geschrieben hatte, der
zu Anfang den gesamten verfügbaren Speicher reserviert und dann selbst organisiert.
Vielleicht wäre das schon die Lösung.
Ich habe mich damit nur nicht länger befasst weil mir der Speicherumgang mit
GetMem und FreeMem so vertraut war und ich bisher keine Probleme mit
Heap-Fragmentierung hatte.

Hallo, Zatzen!

Ja, ich nutze meinen Speichermanager mittlerweile in quasi JEDEM meiner Projekte/Programme.
Es ist schon ein beruhigendes Gefühl, nicht mehr ständig über Speicherreservierung nachdenken zu müssen - alles was zählt, ist, daß alles zusammengenommen den gesamten freien Speicher nicht übersteigen darf (logisch). Wobei ich sagen muß, daß ich in manchen meiner Projekte sogar noch einen Schritt weiter gegangen bin und den Kram dermaßen dynamisch gemacht habe, daß man denken könnte, ich will ne Windows-GUI bauen:
Das ganze war dreistufig, nutzte Heap, XMS und dann auch Festplatte als Auslagerungsspeicher. Das brauchte ich z.B. für Füllfunktionen für große Auflösungen oder für das Retten von Fensterhintergründen bei der GUI meines Grafik/Level/Sprite-Tools.

Naja, an sich ist die Idee hinter meinem Speichermanager recht simpel. Vor jedem reservierten Speicherbereich gibt es einen Header, der unter anderem die Größe, sowie die absolute Position des Pointers enthält (und noch Typen usw...) Das ist wichtig, weil, wenn die Größe später geändert wird oder Speicherbereiche DAVOR vergrößert werden, dann ändert sich ja der Anfang des Speicherbereichs - dazu hat man die Position des Pointers - denn der Speichermanager ändert dann auch automatisch den Pointer - so daß er danach auf die neue Position zeigt.
Wird nun die Größe eines Speicherbereichs geändert, so werden aus allen nachfolgenden "Header" die Pointerpositionen gelesen und in die Pointer selbst werden die verschobenen Positionen geschrieben. (Die Header VOR dem geänderten Speicherbereich bleiben selbstverständlich unbeeinflußt.)
Natürlich werden bei Änderung eines Speicherbereichs, der NICHT der letzte in der "Kette" ist, die ganzen nachfolgenden Speicherbereiche noch umkopiert (verschoben). D.h. es ist natürlich keine gute Idee, andauernd die Größen von Speicherbereichen innerhalb von sehr zeitkritischen Abläufen zu ändern - aber das sollte ja klar sein.

Für XMS habe ich dann noch einmal das gleiche gemacht - da werden als "Pointer" einfach Longint-Variablen benutzt.

Und ja - ich finde dynamische Speichernutzung sehr nützlich - und für größere Projekte, gerade im Heap-Bereich, nahezu unvermeidlich.
DOSferatu
DOS-Übermensch
 
Beiträge: 1095
Registriert: Di 25. Sep 2007, 11:05

Re: Heap-Fragmentierung (Pascal)

Beitragvon wobo » Di 14. Mär 2017, 17:42

zatzen hat geschrieben:Hallo!
...
Nun hätte ich dabei aber das Problem, wenn man Samples reinlädt und der User sich
zwischendurch entscheidet, diese durch andere auszutauschen. Der Heap würde
fragmentiert werden.

Hat jemand einen Ansatz, wie man das vermeiden könnte? ...


1.
Eigenen Speichermanager schreiben, wenn man DosFeratu heißt.

2.
Eingriff in die Speicherverwaltung von TP (mit mir nicht.)

3.
Verwendung von Borland Pascal 7.0 anstelle von TP 7.0. Dann müsstest Du statt max. 640kb Heap knapp 16MB Heap haben (BP 7.0 habe ich nicht).

4.
Brute Force bei TP 7.0: 512 kb XMS (z.B.) allozieren; tritt dann die Situation auf, dass der Heap zu fragmentiert ist, aber dennoch theoretisch genügend Heap frei ist (MemAvail), dann alle Heap – Bereiche in den Xms kopieren, alle Heap-Bereiche freigeben (FreeMem,Dispose), alle Heap-Bereiche neu anlegen und aus dem XMS wieder zurück in den Heap kopieren. Du musst natürlich bei der Ermittlung des Gesamtspeicherbedarfs berücksichtigen, dass TP den Heap immer in 8-byte-Happen verteilt. Ein Speicherbereich mit 33 byte (z.B. GetMem (MyPtr, 33)) verbraucht daher an Heap immer 40 byte usw.

5.
Es wäre nämlich auch für ein Spiel praktikabel, wenn man für verschiedene Levels
unterschiedliche Grafik, Musik und Sounds laden möchte.

Im Game würde ich bei Level-Wechsel immer alle level-relevanten Speicherbereiche am Level – Ende freigeben und bei Beginn des neuen Levels komplett neu anlegen. Dann hast Du auch keine Fragmentierung.
wobo
DOS-Guru
 
Beiträge: 555
Registriert: So 17. Okt 2010, 13:40

Re: Heap-Fragmentierung (Pascal)

Beitragvon zatzen » Mi 15. Mär 2017, 16:25

Abgesehen von einem Speichermanager erscheint mir die Brute Force Variante mir am sympathischsten.
Es wäre ja quasi eine Defragmentierung. Nur würde ich den XMS nicht bemühen wollen,
sondern für meinen eventuellen Tracker lieber eine Auslagerungsdatei benutzen.
Wie schnell oder langsam das wäre müsste man sehen.
Wobei eigentlich, der Tracker ist ja ein Nutzprogramm, da kann man ruhig
XMS voraussetzen, es könnte sowieso etwas eng werden auf dem Heap wegen
der ungepackten Patterns.
Der Hauptsinn für einen ZSM Tracker wäre, dass man direkt hören kann, wie
es hinterher klingt. Die 4 Bit Samples können im ungünstigsten Fall schonmal
ein Sample etwas entstellen, zudem wird ohne Interpolation gemischt, und
ich verwende den anderen Tracker, von dem ich bislang konvertiere, mit Interpolation (GUS).
Aber der Aufwand lohnt sich wohl nicht.
Jedenfalls nicht heute - als ich vor 22 Jahren meinen simplen Adlib-Tracker gemacht
hatte haben doch tatsächlich ein paar Freunde damit etwas komponiert.

Danke jedenfalls Euch für die Antworten. Ich sehe das jetzt deutlich klarer.
Benutzeravatar
zatzen
617K-Frei-Haber
 
Beiträge: 310
Registriert: Di 17. Apr 2012, 04:10
Wohnort: bei Köln

Re: Heap-Fragmentierung (Pascal)

Beitragvon DOSferatu » Do 23. Mär 2017, 19:25

Naja, wie ich bereits erwähnte: Das Ganze ist kein Hexenwerk, ich habe das damals in Pascal gemacht und nutze es immer noch. Ich habe ja geschrieben, wie mein Zeug da ungefähr funktioniert, damit Du vielleicht Deinen eigenen Speichermanager bauen kannst. (Klar - wer will schon fremden Code benutzen?)
Der Gedanke dahinter war nur. einen der möglichen Ansätze dazu zu erklären, so als Denkanstoß.
DOSferatu
DOS-Übermensch
 
Beiträge: 1095
Registriert: Di 25. Sep 2007, 11:05


Zurück zu Programmierung

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast