Garbage Collection Algorithmen - Seminar SS95

Verfahren zur Speicherrueckgabe


Martin Exler, 9126090
Es handelt sich bei diesem Dokument um eine Zusammenfassung der Kapitel 3.4 - 3.4.6 der Diplomarbeit von Ulrich Neumerkl "3.4 Verfahren zur Speicherrueckgabe".
Ausgangspunkt
Nicht mehr referenzierbare Zellen sind bereits erkannt (markiert) worden.
Der freie Platz kann daher wieder vergeben werden. Dafuer gibt es zwei Varianten:
  1. Die freien Zellen werden ueber eine eigene Verwaltung direkt fuer neue Zellen verwendet, oder
  2. man verlegt die referenzierbaren bzw. freien Zellen in einen geschlossenen Bereich.

Mark and Sweep

Nach der Markierungsphase wird der Speicher durchsucht und die freien Zellen werden in einer Freispeicherliste miteinander verkettet. Bei einer Speicheranforderung wird in dieser Liste nach einem passenden Speicherbereich gesucht.

Anmerkungen:

Dijkstras On-the-Fly

Vollkommene Parallelisiserung der Markierungs- und Reorganisationsphase: Die Markierung verwendet 3 verschiedene Zustaende fuer jede Speicherzelle: Der mutator unterstuetzt die Markierungsphase dadurch, dasz er die weiszen Zellen, die er verwendet auf grau setzt. Auszerdem sendet er dem collector ein Triggersignal, wenn die Freispeicherliste nur mehr eine Zelle enthaelt. Der mutator musz dann solange warten, bis der collector mindestens eine weitere Speicherzelle verfuegbar gemacht hat.

Der collector musz die benutzten Zellen, die Zellen in der Freispeicherliste und alle grauen Zellen markieren. Zuerst setzt er die erste benutzte und die erste Zelle der Freispeicherliste auf grau. Dann werden alle Zellen, die durch eine graue Zelle z referenzierbar sind auf grau gesetzt und anschlieszend wird z auf schwarz gesetzt.

Am Ende des Durchlaufes werden die weiszen Zellen in die Freispeicherliste eingehaengt und danach werden die schwarzen Zellen weisz gefaerbt. Dadurch werden inaktive graue Zellen zuerst schwarz und dann weisz. Im naechsten Durchlauf werden diese Zellen dann in die Freispeicherliste eingehaengt.

Anmerkungen:

Abraham & Patel

Solange der mutator auf einer Seite nichts geaendert hat, wird fuer mutator und collector dieselbe Seite verwendet. Beschreibt er eine Zelle der Seite, so musz fuer mutator und collector jeweils eine eigene Repraesentation der Seite erstellt werden, spaeter werden diese Repraesentationen wieder vereinigt.

Kompaktierende Algorithmen

Knuths LISP2

Jede Speicherzelle enthaelt ein eigenes Feld, in dem ihre neue Adresse steht (dieses Feld wird auch zur Markierung verwendet).

Vorgangsweise:

  1. entsprechend der Markierung neue Adressen fuer die Zellen berechnen/speichern
  2. alle Zeiger auf die neuen Adressen aktuallisieren
  3. alle Elemente kopieren

Anmerkungen:

Table Compactors, Haddon & Waite, Wegbreit

Es wird gleich mit dem Verschieben begonnen, die Verschiebungen werden in einer Tabelle mitprotokolliert.

Vorgangsweise:

  1. Die aktiven Zellen werden einzeln verschoben, dabei wird immer ein entsprechender Eintrag in die Tabelle eingetragen (man kann die Tabelle "rollen" um einen benoetigten Speicherbereich benutzen zu koennen).
  2. Die Tabelle wird sortiert.
  3. Die Zeiger werden mit Hilfe der Tabelle aktuallisiert


Table-Compactor während Phase I

Anmerkungen:

Edwards Kompaktierer

Vorgangsweise:
  1. Es werden 2 Zeiger verwendet, mit dem einem sucht man freie Zellen, mit dem anderen (in entgegengesetzter Richtung) nach markierte Zellen. Die markierten Zellen werden in die freien Zellen kopiert, in der alten Zelle wird ein Zeiger auf die neue Position gespeichert. Treffen sich die beiden Zeiger, so ist man fertig.
  2. Suche die Zeiger, die auf verschobene Zellen zeigen und aktuallisiere sie.

Anmerkungen:

Kopieralgorithmen

Kopieralgorithmen kombinieren Markierung und Kopieren der Zellen in einer Phase. Nach dem vollstaendigen Durchlauf befinden sich alle aktiven Zellen in einem durchgehenden Block. Der restliche Speicher ist frei.

Anmerkungen:

Minsky

Fuer alle aktiven Zellen wird jeweils ein Tripel (zukuenftige Position der Zelle, rechter und linker Zeiger) berechnet und in einer Datei gespeichert. Die neue Adresse wird auszerdem in der markierten Zelle gespeichert. Nach der Kompaktierung stehen Zellen die miteinander verbunden sind im Hauptspeicher nahe beisammen.

Fenichel-Jochelson - Twospace Kompaktierung

Der Speicher wird in zwei gleich grosze Bereiche A und B aufgeteilt. Zuerst werden alle Speicherelemente in A angelegt. Ist hier der Platz erschoepft, so kopiert man die Zellen nach B. In A wird ein Verweis auf die neue Position abgespeichert. Trifft man beim Kopieren auf einen solchen Verweis, so verwendet man diesen als Wert. Anschlieszend wird B zum aktiven Bereich.

Scavening Algorithms

Bakers Kopieralgorithmus
Der Speicher wird in zwei gleich grosze Bereiche aufgeteilt. Es werden aber nicht alle Zellen auf einmal in den neuen Bereich kopiert, sondern zuerst nur eine fixe Anzahl von Elementen. Im Zuge der weiteren Ausfuehrung des Programmes wird nun: Anmerkungen:
Ringkompaktierung
Hier wird nicht zwischen zwei abgegrenzten Bereichen hin- und herkopiert, sondern der Speicher wird als Ringspeicher angesehen. Der aktive Bereich durchwandert den Speicher, auf der einen Seite werden neue Elemente angelegt, auf der anderen Seite laeszt man nur freie Zellen zurueck. D.h. mueszte man eine aktive Zelle zuruecklassen, so wird sie an den Anfang des aktiven Bereiches kopiert.


MALI's Ringkompaktierer

Liebermann und Hewitt
Der Speicher wird in viele kleinere Bereiche aufgeteilt. Dadurch ist es moeglich sowohl kurzlebige als auch permanente Datenstrukturen effizient zu verwalten.

Jeder Speicherbereich enthaelt eine Generations- und Versionsnummer. Da in LISP fast nur Zeiger von juengeren Zellen auf aeltere Zellen erzeugt werden, koennen juengere Generationen unabhaengig von aelteren behandelt werden.

Dieses Verfahren eignet sich auch besonders fuer Prolog, da es keinen Mehraufwand zur Laufzeit benoetigt - die Generationen werden hier schon von der Semantik der Sprache benoetigt.

Ungar generation scavenging
Dieses Verfahren wurde im Hinblick auf Smalltalk entwickelt. Es geht auch auf die typische Lebenserwartung der Zellen ein. Die neuen Zellen werden in 3 verschiedene Bereiche unterteilt:
  1. New Space zur Allokierung neuer Zellen
  2. PastSurvivorSpace Zellen, die bereits eine Bereinigung hinter sich haben
  3. FutureSurvivorSpace wird das Ziel des naechsten Kopierens
Vorgangsweise:
  1. Die erreichbaren Zellen aus NewSpace und PastSurvivorSpace werden in den FutureSurvivorSpace kopiert.
  2. Past- und FutureSurvivorSpace werden vertauscht.
  3. Ist eine Zelle lange genug neu, dann wird sie alt (und in den entsprechenden Bereich kopiert).
Anmerkungen:
/usr/gtp/pub/ulrich/gc