Reference Counting II
Freigeben zyklischer Zellstrukturen
1 1 2
1
1
Wurzel
0
0
1
Wie entstehen Zyklen?
• Systemebene?
• Programmebene?
Wie lassen sich Zyklen vermeiden?
Bobrow‘s Technik
Ansatzpunkt Behandle einen Zyklus wie eine einzelnes Objekt
G G
G
externe Zelle 1
RC Gruppe G: 3 RC Gruppe H: 1
… externe Zelle 2
externe Zelle 3
Aber wie wird ein Zyklus erkannt?
Bobrow‘s Technik
Realisierungstechniken der Gruppen
Zonenbasiertes Gruppieren:
• z.B.: Ableiten der Gruppe aus der Adresse
Speicherverschnitt
Beschriftende Gruppierungsverfahren:
• Zellenbeschriftung
• Zeiger auf das RC Feld Beide fix oder variabel
Verschmelzen von Gruppen
G G
G
externe Zelle 1 RC Gruppe G: 3
RC Gruppe H: 1
…
externe Zelle 2
externe Zelle 3
Gruppe G Gruppe F
Gruppe H
Weak- Pointer Algorithmen
Grundidee:
Unterteilen in 2 Kategorien von Pointern Normale RC- Verfahren auch für Zyklen Arbeiten von:
Brownbridge, Salkild und Pepels.
Invarianten:
• Jeder aktive Knoten kann vom der Wurzel her über einen Pfad von starken Referenzen erreicht werden.
• starke Referenzen dürfen niemals einen Zyklus schließen.
1 1
1
Wurzel
Brownbridge‘s Algorithmus
Eckdaten:
Zwei Reference Count Felder.
Ein Zeiger auf eine neue Zelle ist immer stark.
Kopieren eines Pointers kann zu starken Zyklus führen!
Brownbridge beschäftige sich nicht mit allgemeinen Pointer Systemen!
Problemillustration:
B
1 0
1 1
1 1
2 0
1 0 Wurzel
A
C
D
E
Salkild‘s Modifikationen
Ein kopierter Zeiger ist immer schwach
Das Löschen gestaltet sich komplizierter (3 Fälle)
//Fall 3: nur noch schwache Referenzen else if(SRC(P) == 0 && WRC(P) > 0){
invertStrength(P);
forall(Children C of P){
suicide(P,C);
}
if(SRC(P) == 0){
forall(Children C of P){
delete(C);
}
free(T);
} }
B 1 0
1 1
1 1
2 0
1 0 Wurzel
A
C
D
E
Salkild‘s Modifikationen
/**
* Suchroutine die starke Zyklen von
* einem Knoten ’Start’ aus findet und
* Diese beseitigt.
*/
void suicide(pointer Start, pointer N){
if(isStrong(N)){
if(N == Start || SRC(N) > 1){
weaken(N);
}
else{
forall(Children T of N)){
suicide(Start, T);
} } }
} B
1 0
1 1
1 1
2 0
1 0 Wurzel
A
C
D
E
1
2 1
1
Wurzel
Pepels‘s Modifikationen
Lösen Salkild‘s Terminierngsproblem
Verwendet ein doppeltes Markierungsschema
1. verhindert unendliche Anzahl von Suchen
2. garantiert das Terminieren einer Suche
größerer Speicherbedarf
Problem mit der Laufzeitkomplexität (exponentiell)
Brownbridge‘s Realisierung
Jedes Objekt und jeder Pointer wird mit einem Stärkebit versehen
Bitwert Pointer = Bitwert Objekt starker Pointer
Der Stärkewert einer Zelle bestimmt was SRC bzw. WRC ist
Stärkewert alle eingehenden Pointer kann damit in einer Operation invertiert werden
Aufgrund der Systemoperationen Vorteilhaft
Partielle Mark-Sweep Algorithmen
Hybride Algorithmen (Reference Counting Mark-Sweep)
Mark-Sweep ist nur für Zyklen zuständig
Mark-Sweep soll so wenig als möglich zum Einsatz kommen
Dreiphasiges Verfahren:
1. Einfluss interner Pointer aufheben
2. Traversieren und Reference Counts wieder herstellen
3. Entfernen der nicht erreichbaren Zellen
1 1
2
Externer Knoten
Lins‘s Algorithmus
Lazy cyclic Reference Counting
1. Aufschieben durch Einsatz eines Control Sets
2. Einfach referenzierte Zellen werden sofort freigegeben
3. Sammeln potentiell freizugebender Zellen
4. Zustände in Form eines Farbschemas (hier: schwarz, grau, weiß, violett)
Farbübergänge
1. weiß schwarz: Reservieren der Zelle, beim Collection cycle
2. schwarz violett: Löschen eines mehrfach ref. Pointers
3. violett schwarz: Update auf Zelle
4. violett, schwarz grau: markGrey Phase (1)
5. grau schwarz: scanBlack Phase (2)
Vermeiden von Mehrfachreferenzen im Control Set
Lins‘s Algorithmus
Mark-Sweep Collection Cycle
void markGrey(cell C){
if(colour(C) != grey){
colour(C) = grey;
forall(Children T of C){
RC(T) = RC(T) - 1;
markGrey(T);
} } }
void scan(cell C){
if(colour(C) == grey){
if(RC(C) > 0){
scanBlack(C);
}
else{
colour(C) = white;
forall(Children T of C){
scan(T);
} } } }
void scanBlack(cell C){
colour(C) = black;
forall(Children T of C){
RC(T) = RC(T) + 1;
if(colour(T) != black){
scanBlack(T);
} } void collectControlSet(){
cell C = ControlSet.getCell();
if(colour(C) == violet){
marGrey(C);
scan(C);
collectWhite(C);
}
else if(!ControlSet.empty()){
collectControlSet();
} }
Lins‘s Algorithmus
B 1 2
1 2
1 Wurzel
A
C
D
E
B 0 0
0 1
0 Wurzel
A
C
D
E
Phase 1: markGrey
Lins‘s Algorithmus
B 0 0
0
1
1 Wurzel
A
C
D
E
1
1 Wurzel
D
E
Phase 3: collectWhite
Lins‘s Algorithmus
Control Set Strategien
Bewirtschaftungsstrategie
Teil Abarbeitungsstrategie
Realisierungstechnik des Control Sets
collectWhite Strategien
Erfolgsrezept
großteils einmalige Referenzierung
Zyklen hinreichend klein
violette Phase hält nicht allzu lange an
Lins‘s Algorithmus
Kombination mit gewichtetem RC
Wenig Kommunikation- Garbagecollection in verteilten Systemen
Synchronisation der Phasen notwendig
Variabilität des Verfahrens wegen unterschiedlichen Synchronisationen noch größer
16 16
16 A
B
C
16
16 16
16 A
B
C
8 8
Erzeugen des Pointers <B,C>
Resümee
Pro
Einfach und verständlich
Kann mit programmiertechnischer Freigabe vermischt werden
Rechenaufwand verzahnt gut mit Nutzprogramm
Contra
Sehr anfällig wenn ein Fehler aufgetreten ist
Selten bis nie in großen kommerziellen Systemen
Zyklen in den Zellen bedeuten erhöhte Rechenzeit
Literatur
[Bobrow80] Bobrow, D.: Managing Reentrant Structures Using Reference Counts. ACM TOPLAS 2(3):269-273, 1980
[Jones92] Jones, R, Lins, R.: Cyclic weighted reference counting without delay. Computing Laboratory, The University of Kent at Canterbury. Technical Report 28-92. 1992.
[Jones96] Jones, R, Lins, R.: Garbage Collection: Algorithms for Automatic Dynamic Memory Management. John Wiley 1996