RazorSPoint

WP7: Weg mit Mark-Sweep und her mit dem Generational GC

Sebastian SchützeSebastian Schütze

Der Blog Post dient mehr dazu das Wissen für mich zu verinnerlichen und den neuen Garbage Collector für das WP7 Version “Mango” anderen etwas näher zu bringen.

Der Garbage Collector

Was zu Deutsch Müllabfuhr bedeutet, wird in der Informatik eher als automatische Speicherbereinigung bezeichnet. Doch was macht einen Garbage Collector aus? Wenn Variablen verwendet werden oder generell Speicher reserviert (alloziiert) werden muss, dann müssen mehrere Punkte beachtet werden. Fehler die einen dabei sofort in den Sinn kommen sind:

Dies sind jedoch nur die häufigsten Fehler. Diese Fehler lassen sich jedoch leicht vermeiden. Daher besitzen Java wie auch Sprachen im .NET Bereich einen Garbage Collector. Dieser kümmert sich ganz einfach um die Allokation von Variablen und die Bereinigung von nicht mehr benötigtem Speicher.

Es gibt mehrere Algorithmen für die Garbage Collection, aber für WP7 sind nur zwei interessant:

  1. der alte (noch aktuelle) Mark-Sweep-Compact
  2. der neue (in Mango) Mark-Sweep-Compact mit Generational Flag

der neue hat letztendlich den Effekt, dass die Laufzeit wesentlich verkürzt wird, da die im managed Heap enthaltenen manged Objects nicht alle durchsucht werden müssen.

Mark-Sweep-Algorithmus

Man stellt sich vor man habe Objekte im Heap, die Abhängigkeiten wie auf dem Objektgraph in Abbildung 1 haben.

Abbildung 1: Objektgraph mit Abhängigkeiten der Objekte

Nun sieht man, dass wir zwei Wurzeln haben und von der Wurzel aus verschiedenste andere Knoten direkt oder indirekt über andere Knoten erreichbar sind. Die Erreichbarkeit bezieht sich darauf, dass sie von Programmcode während der Laufzeit erreichbar sind. Sie können Referenzen auf Methoden, Parameter, lokale und globale Variablen zeigen. Ein Objekt ist jedoch nicht erreichbar (Objekt c) was bedeutet, dass dieses Objekt nicht mehr benötigt wird.

Im ersten Teil des Algorithmus (Mark) würde vom Wurzelknoten aus gestartet werden und jedes Objekt, welches von der Wurzel erreichbar ist wird markiert. Die Markierung besagt nichts anderes, dass dieses Objekt nicht freigegeben werden darf und die Referenzen erhalten bleiben sollen. Die Markierung ist eine Information, welche im Header jeden Objektes gespeichert wird.

Abbildung 2: Objekte und ihre Abhängigkeiten im Heap

Im Falle unserer Graphik wurden nun alle Objekte die von den Wurzeln erreichbar sind grün markiert (Abbildung 3). Dier zweite Teil ist nun der “Sweep”-Teil. Objekt c ist nun zum freigeben bzw. wiederverwenden markiert.

Abbildung 3: die markierten Objekte, welche nicht gelöscht werden.

Nun sind Objekte freigegeben (Abbildung 4). An sich wäre der GC fertig und die Stellen können wieder verwendet werden. Jedoch ist der Speicher nun fragmentiert, was die spätere Suche nach freien Stellen erschwert. Zudem gibt es bei stark fragmentiertem Speicher nicht größere zusammenhängende freie Speicherbereiche, sondern viele kleine. Dadurch müssen Daten, die größer als ein freie zusammenhängender Speicherbereich sind, aufgeteilt und und getrennt gespeichert werden. Die erhöht natürlich die Ladezeit. Daher werden die

Abbildung 4: Der Heap mit freigegebenem Speicher.

Objekte kompakt zusammen geschoben, indem die Objekte verschoben und Referenzen auf Objekte aktualisiert werden. (Abbildung 05)

Abbildung 5: Speicher mit zusammen geschobenen Objekten ocken

Der Generational Ansatz

Das Problem ans einem normalen GC so wie oben beschrieben ist, dass beim bereinigen des Speichers die komplette Anwendung eingefroren wird, damit sich der Heap nicht verändert während der Bereinigung. Schlimm wird es, wenn der Speicher sehr voll wird. Ich selbst hatte Apps auf dem WP7, welche leicht 60MB Ram verbraucht haben. Der Heap kann bei großen Anwendungen sogar bis zu 100MB betragen. Es existieren sehr viele Objekte in solche einem Fall im Heap, welche sich teilweise exponentiell vermehren. Somit sind auch immer mehr Referenzen zu verfolgen, was die Suche nach nicht zu löschenden Objekten natürlich sehr komplex gestalten kann.

Jedoch ist nach den Blogposts von Abhinaba Basu zum GC Fakt, dass die meisten Objekte nicht lange leben. Objekte die jedoch länger im Speicher sind, werden sehr wahrscheinlich auch noch länger im Heap bleiben. Wie man sieht, kann man diese Objekte in zwei Generationen (Gruppen) einteilen. Generation 0 (Gen0 Collection) sind die kurzlebigen Objekte, während Generation 1 (Gen1 Collection) die langlebigen sind. Objekte aus Gen0 können nach Gen1 erweitert werden.

Nachdem man nun weiß, dass die gen0 collection sehr klein ist, kann diese auch gewissenhaft durchsucht werden und alle nicht erreichbaren Objekte in kurzer Zeit gelöscht werden. Es existiert jedoch noch ein weiteres Problem. Es gibt Objekte, die von Gen1 auf Gen0 verweisen. Dies würde bedeuten, dass man doch wieder in die Gen1 Collection rein müsste um die entsprechenden Gen0 Objekte zu finden. Resultat: hohe Laufzeiten.

Also was wird gemacht? Jedesmal, wenn im generierten JIT-Code eine Referenz erstellt oder verändert wird, dann wird dies in einer zusätzlichen Tabelle gespeichert, die sogenannte Card-Table. Nun sind diese Referenzen gespeichert und können sehr schnell durchsucht werden.

Zusammenfassend werden also nur zwei Typen von Referenzen überprüft:

Performance “Juchhe”

Damit müsste klar sein, dass nun Apps wesentlich schneller starten müssten bzw. kürzere Zwischenladezeiten existieren werden. Im besten Fall spart man sich mehrere hundert Millisekunden Ladezeit. Wer mehr über WP7 als Deep Dive wissen möchte, dem emfpehle ich den Blog von Abhinaba Basu

Verwendete Links:

http://blogs.msdn.com/b/abhinaba/archive/2011/06/08/wp7-mango-mark-sweep-collection-and-how-does-a-generational-gc-help.aspx

http://blogs.msdn.com/b/abhinaba/archive/2011/06/14/wp7-mango-the-new-generational-gc.aspx

http://blogs.msdn.com/b/abhinaba/archive/2011/04/13/generational-gc-in-windows-phone-mango.aspx

http://www.virtualmachine.de/2000-ernst-schneider/node17.html

http://blogs.msdn.com/b/abhinaba/archive/2009/01/25/back-to-basic-series-on-dynamic-memory-management.aspx

Sebastian is an Azure Nerd with focus on DevOps and Azure DevOps (formerly VSTS) that converted from the big world of SharePoint and O365. He was working with O365 since 2013 and loved it ever since. As his focus shifted in 2017 to more DevOps related topics in the Microsoft Stack. He learned to love the possibilities of automation. Besides writing articles in his blog and German magazines, he is still contributing to the SharePoint Developer Community (and PnP SharePoint) to help to make the ALM part a smoother place to live in.

Comments 0
There are currently no comments.

This site uses Akismet to reduce spam. Learn how your comment data is processed.