Folie - System Software

Werbung
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 1 / 20
Thomas Negeli | 0255604
[email protected]
Reference Counting I
Negeli Thomas (0255604 / 521)
Student an der Johannes Kepler Universität Linz, Österreich
Präsentation für: Seminar Garbage Collection WS2005 339.372
[email protected]
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 2 / 20
Thomas Negeli | 0255604
[email protected]
Invariante: RC = 0  Zelle ist unbenutzt
Zeiger auf Zelle vom Heap oder vom Stack setzen  inkrement des RC
Zeiger löschen  dekrement des RC
Algorithmus 1 - Anforderung von Speicher:
/** Speicherzelle anlegen */
MemoryCell New() {
if (free_list == null)
/** Abbruch, kein Speicher
* mehr frei */
System.exit(1);
newCell = allocate();
newCell.rc = 1; //ReferenceCount
return newCell;
}
/** Speicher anfordern */
MemoryCell allocate() {
newCell = free_list.pop();
free_list = free_list.next;
return newCell;
}
free_list:
Menge an freien Speicherzellen
newCell:
einfache freie Speicherzelle
allocate():
liefert eine neue freie Speicherzelle
new():
verwaltet Referenzzähler und Speicherplatz
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 3 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 2 – Überschreiben von Zellen:
/** Update von Objekten */
void Update(MemoryCell r, MemoryCell s) {
delete(r);
s.rc++;
r = s;
}
Update(r,s) überschreibt r mit s
/** Löschen von Referenzen */
void delete(MemoryCell t) {
t.rc--;
if(t.rc == 0) {
if (t.next != null)
delete(t);
free(t);
}
}
delete(t) löscht rekursiv alle Kinder von t
/** Speicher freigeben */
void free(MemoryCell t) {
t.next = free_list;
free_list = t;
}
free(t) gibt den Speicher von t frei
Reference Counting I
Seminar Garbage Collection
339.372 | WS2005
Thomas Negeli | 0255604
[email protected]
Folie 4 / 20
Stärken und Schwächen des Reference Counting
Vorteile
Einfache Handhabung der Algorithmen
Speicherverwaltung und Programmausführung laufen
verschränkt ab  bietet sich für Echtzeitsysteme an
Problem: Rekursivität von Algorithmus 2 durch Löschen der
Kinder
Räumliche Lokalität der Referenzen
Zelle ohne Zugriff auf andere Zellen im Heap zurückfordern
(Kinder bilden Ausnahme)
Problem: ev. Cache Miss bzw. Page Fault
Studien belegen: wenige Zellen sind
shared, viele existieren nur kurzzeitig
Algorithmus 1 und 2 erlauben sofortige Wiederverwendung
 Weniger Page Faults, Cache Misses als Tracing
Strategien
leicht abgeänderte Kopie : Zeiger
ausborgen (Glasgow Haskell compiler)
finalisation actions
Nachteile
Aufwand zur Aufrechterhaltung der
Invariante
Werte in alter und neuer Zelle justieren
Starke Kopplung an das Speichermanagement des Benutzerprogrammes
bzw. Compilers
 Zerbrechliche Strategie
Extra Speicherplatz in jeder Zelle
Maximaler RC Wert = Anzahl der Pointer
Problem mit zyklischen Datenstrukturen
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 5 / 20
Thomas Negeli | 0255604
[email protected]
Löschen des Zeigers von R nach S macht den
Teilbaum S, T, U unzugänglich
Freigabe aufgrund der RC Werte nicht möglich
Lösung:
Reference Counting bis Heap voll ist
Anschließend Tracing:
* Alle Counts auf 0 setzen
* inkrementieren jeder aktiven Zelle in der Markierungsphase
* unmarkierte Zellen löschen
 Kleinere Count Felder möglich, Tracing verwaltet maximale Zählerstände
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 6 / 20
Thomas Negeli | 0255604
[email protected]
Problem: rekursives Löschen der Kinder eines Knotens in der delete(…) Methode
 Strategien überlegen um Rekursivität zu entfernen, da Löschaufwand vom Subgraph abhängt
Algorithmus 3 + 4 – Weizenbaum‘s lazy freeing:
/** Speicherzelle anlegen */
MemoryCell New() {
if (free_list == null)
/** Abbruch, kein Speicher
* mehr frei */
System.exit(1);
newCell = allocate();
if(newCell.next != null)
delete(newCell);
newCell.rc = 1; //ReferenceCount
return newCell;
}
delete(t) =
if (t.rc==1) {
t.rc = free_list
free_list = t
}
else decrementRC(t)
Löschen der Kinder erfolgt nicht mehr bei der Freigabe der Zelle, sondern bei der Anforderung von neuem
Speicher.
RC Feld dient nun der Verkettung der freien Zellen  t ist ein Zeiger auf ein Heap Element.
Zeiger speichert den Count Wert, nicht die Zelle.
Problem nur teilweise gelöst: Schneller bei kaskadierten Freigaben. Problem wurde nur verschoben, eventuell
Verschwendung von Speicherplatz.
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 7 / 20
Thomas Negeli | 0255604
[email protected]
Verwaltungsaufwand macht RC unattraktiv gegenüber Tracing Strategien (scheinbar)
• Überschreiben von Zeigern erfordert einigen Aufwand
• Sogar Unterprogrammaufrufe erfordern Justierungen
• Caches werden oft mit nicht benötigten Daten gefüllt
Daten werden verändert und müssen wieder zurückgeschrieben werden obwohl wieder der
Ausgangszustand hergestellt wurde
Lösung:
Unnötige Veränderung der Count Werte nach Möglichkeit vermeiden (aufschieben)
Manuell, bei Wissen über Unterprogramme, kein Problem, jedoch aufwändig
Optimierung durch Compiler (Anpassungen nötig)
Besser: Verwaltung zur Laufzeit durch z.B. Deutsch-Bobrow Algorithmus
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 8 / 20
Thomas Negeli | 0255604
[email protected]
Studien haben gezeigt: Hauptteil von Zeigermanipulationen erfolgt im Stack. Andere
Operationen haben einen Anteil von 1%
 Operationen auf lokale Variablen optimieren
Algorithmus 5 – nach Deutsch-Bobrow
Kein RC für lokale Variablen
einfache Zuweisungen bei Manipulationen
möglich, Update weniger komplex
Count Werte bedeuten jetzt
Referenzen von anderen Heap
Objekten
Keine Freigabe wenn RC = 0, einfügen in
eine Zero Count Table (ZCT)
/** Update von Objekten */
void Update(MemoryCell r, MemoryCell s) {
delete(r);
s.rc++;
ZCT.remove(s);
r = s;
}
/** Löschen von Referenzen */
void delete(MemoryCell t) {
t.decrementRC();
if (t.rc==0) {
ZCT.put(t);
}
}
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 9 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 6 – Aufräumen des Speichers
Aufräumen des Speichers in 3 Stufen:
1.
2.
3.
void reconcile() {
/** markieren der Elemente */
for(i=0; i<stack.getSize(); i++) {
stack.getElem(i).incrementRC();
}
Alle Elemente der ZCT mit Referenzen aus
dem Stack werden markiert
Alle nicht markierten Elemente entfernen
Alle Markierungen entfernen
/** unreferenzierte Zellen
* löschen */
for(i=0; i<ZCT.getSize(); i++) {
cell = ZCT.getElement(i);
if (cell.rc == 0) {
if (cell.next!=null)
delete(cell);
free(cell);
}
}
/** Markierungen entfernen */
for(i=0; i<stack.getSize(); i++) {
stack.getElem(i).decrementRC();
}
}
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 10 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 7 – größter gemeinsamer Teiler
/** Größter gemeinsamer Teiler
* Bedingung: x >= y >= 0 */
int gcd(int x, int y) {
if (y == 0)
return x;
t = x-y;
if (x>t)
return gcd(y,t);
else
return gcd(t,y);
}
Getroffene Konventionen:
• Alle Objekte werden am Heap abgelegt
• Ausdrücke werden als Graph dargestellt dessen Knoten Objekte am Heap sind
• Der System Stack enthält Zeiger auf Heap Objekte
• Atomare Objekte werden mit ihrem Wert bezeichnet
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 11 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 7 – größter gemeinsamer Teiler
/** Größter gemeinsamer Teiler
* Bedingung: x >= y >= 0 */
int gcd(int x, int y) {
if (y == 0)
return x;
t = x-y;
if (x>t)
return gcd(y,t);
else
return gcd(t,y);
}
Getroffene Konventionen:
• Alle Objekte werden am Heap abgelegt
• Ausdrücke werden als Graph dargestellt dessen Knoten Objekte am Heap sind
• Der System Stack enthält Zeiger auf Heap Objekte
• Atomare Objekte werden mit ihrem Wert bezeichnet
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 12 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 7 – größter gemeinsamer Teiler
/** Größter gemeinsamer Teiler Getroffene Konventionen:
* Bedingung: x >= y >= 0 */
• Alle Objekte werden am Heap abgelegt
int gcd(int x, int y) {
• Ausdrücke werden als Graph dargestellt dessen Knoten Objekte am Heap sind
if (y == 0)
return x;
• Der System Stack enthält Zeiger auf Heap Objekte
t = x-y;
• Atomare Objekte werden mit ihrem Wert bezeichnet
if (x>t)
return gcd(y,t);
Update(right(R),6)
else
return gcd(t,y);
Update(left(R),B)
}
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 13 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 7 – größter gemeinsamer Teiler
/** Größter gemeinsamer Teiler
* Bedingung: x >= y >= 0 */
int gcd(int x, int y) {
if (y == 0)
return x;
t = x-y;
if (x>t)
return gcd(y,t);
else
return gcd(t,y);
}
Zustand nach
reconcile()
Getroffene Konventionen:
• Alle Objekte werden am Heap abgelegt
• Ausdrücke werden als Graph dargestellt dessen Knoten Objekte am Heap sind
• Der System Stack enthält Zeiger auf Heap Objekte
• Atomare Objekte werden mit ihrem Wert bezeichnet
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 14 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 7 – größter gemeinsamer Teiler
/** Größter gemeinsamer Teiler
* Bedingung: x >= y >= 0 */
int gcd(int x, int y) {
if (y == 0)
return x;
t = x-y;
if (x>t)
return gcd(y,t);
else
return gcd(t,y);
}
Das Spiel beginnt
wieder von Vorne.
Getroffene Konventionen:
• Alle Objekte werden am Heap abgelegt
• Ausdrücke werden als Graph dargestellt dessen Knoten Objekte am Heap sind
• Der System Stack enthält Zeiger auf Heap Objekte
• Atomare Objekte werden mit ihrem Wert bezeichnet
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Thomas Negeli | 0255604
[email protected]
Folie 15 / 20
reconcile() wird bei Überlauf der ZCT gestartet
Problem wenn mehrere Zellen gleichzeitig freigegeben werden
Mögliche Lösungen:
1.
Freigabe der Zelle die den Überlauf verursacht wird erst beim nächsten reconcile() durchgeführt
2.
Anpassung des Weizenbaum Algorithmus. Zeiger erst bei erneuter Anforderung der Zelle löschen, tritt
dann ein Überlauf auf, reconcile() anstoßen.
Verfahren reduziert Kosten bei Schreibvorgängen auf Zeiger
%-Werte der absoluten
Ausführungszeit.
Versuch mit Smalltalk
Programmiersprache
Nachteil des Verfahrens:
keine sofortige Freigabe von Speicher der nicht mehr benötigt wird (erst im
reconcile())
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 16 / 20
Thomas Negeli | 0255604
[email protected]
Problem des Speicherplatzes beim Reference Count Feld
Schlimmster Fall: max. mögliche Anzahl Zeiger einer Architektur speichern
ABER:
Praktisch nie so hohe Zählerstände  Speicher sparen, jedoch Überläufe behandeln
Algorithmus 8 – sticky Zählerstände
/** Referenzzähler Dekrement mit
* Sticky Wert */
public void decrementRC() {
if (this.rc < sticky)
this.rc--;
}
/** Referenzzähler Inkrement mit
* Sticky Wert */
public void incrementRC() {
if (this.rc < sticky)
this.rc++;
}
1. Maximal zulässiger Wert eines Zählers
darf nicht überschritten werden
2. Maximaler Wert erreicht  bleibt sticky
Reference Counting kann Zellen die sticky
sind nie mehr freigeben!
 Tracing nötig
Reference Counting I
Seminar Garbage Collection
339.372 | WS2005
Folie 17 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 9 – einfacher Mark & Sweep
Strategie:
1. Heap durchwandern
und alle Count Werte
auf 0 setzen
2. Markieren aller aktiven
Zellen
void mark_sweep() {
/** löschen aller Count Werte */
for(i=0; i<Heap.SIZE; i++) {
Heap.getCell(i).rc = 0;
}
/** markieren aller referenzierten Zellen */
for(i=0; i<Stack.SIZE; i++) {
mark(Stack.getCell(i));
}
3. Zelle erreicht
ursprünglichen Wert an
Referenzen bzw. sticky
Wert
/** bereinigen des Speichers */
sweep();
if (free_list==null)
/** Abbruch, kein Speicher mehr frei */
System.exit(1);
}
mark(…)
arbeitet
rekursiv.
void mark(MemoryCell mc) {
mc.incrementRC();
if(mc.rc==1) {
/** rekursiv alle Kinder markieren */
if(mc.next!=null)
mark(mc.next);
}
}
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 18 / 20
Thomas Negeli | 0255604
[email protected]
Reduzierung des Count Feldes auf 1 Bit  Zelle entweder sticky oder nicht (nicht genauer)
Hauptteil der Zellen ist nicht shared  Optimierungen hier ansetzen
Ziele:
1. Hinauszögern der Garbage Collection
2. Verwaltungsspeicherplatz reduzieren
3. Vermeidung unnötiger Kopien  z.B. Arrays mit tausenden Elementen
Algorithmus 10 – 1 Bit Counting
Update(R,S) =
delete(*R)
T = sticky(*S)
if RC(*S) == unique
*S = T
*R = T
Sticky Bit wandert von der Zelle in den Zeiger = Tagging
Auslesen der Zelle selbst vermeiden
 weniger Cache Misses bzw. Page Faults
Reference Counting + Tracing um Zellen wieder unique machen zu können
Count Bit vom Zeiger in den Knoten  mark Bit von mark_sweep() benutzen
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 19 / 20
Thomas Negeli | 0255604
[email protected]
Algorithmus 11 – Ought to be Two Cache
N = select(N)
Software Cache für Zellen deren Wert eigentlich 2 ist
/** Update von Objekten */
void Update(MemoryCell r, MemoryCell s){
if(s.rc==unique)
insert(s);
delete(r);
r = s;
}
/** Cache füllen */
void insert(MemoryCell s) {
if(hit(s))
/** markieren wenn bereits
* im Cache */
s.rc = sticky;
else
cache.put(s);
}
/** Löschen von Referenzen */
void delete(MemoryCell t) {
if(!hit(t)) {
if(t.rc == unique) {
if(t.next!=null)
delete(t.next);
free(t);
}
}
/** Überprüfen ob Zelle bereits im
* Cache ist */
boolean hit(MemoryCell s) {
if(cache.contains(s)) {
cache.remove(s);
return true;
}
else return false;
}
Seminar Garbage Collection
339.372 | WS2005
Reference Counting I
Folie 20 / 20
Thomas Negeli | 0255604
[email protected]
Reference Counting per Hardware
self-managing heap memories based on reference counting
Aktiver Speicher mit Intelligenz = RCM (Reference Counting Memory) Bänke
Einfacher Einsatz in Multiprozessor Systemen
Spezielle Architektur  hohe Entwicklungskosten  hohe Kosten für den Endkunden da wenig Absatz
Lösung: vorgaukeln einer regulären Speicherbank
Standard Datenspeicher + RCM Bereich
Jeder Bereich hat eigenen Bus und eigene Ports
Je Bereich eine eigene Liste an freiem speicher
Performance abhängig von Problemgröße
Herunterladen