Schlüssel Elemente
		
		
		...  [ Seminar Programmiersprachen und virtuelle Maschinen ]  ...  [ Google's V8 ]  ...
		[ << Einführung ]  ...  [ Kürzliche Entwicklungen >> ]  ...
		
		Übersicht: Schlüssel Elemente
		
		
		
		Speicher Modell der V8
		Das Speicher Modell der V8 arbeitet mit 32 Bit tagged Pointer. Tagged Pointer werden in VMs häufig benutzt, um Zeiger zu kennzeichnen. In der V8 erfolgt dies direkt im Datenwort.
		Außerdem bestehen die Datenworte 4 aligned Byte. Dadurch werden nur Vielfache von 4 als Adresse genutzt und somit sind die letzten 2 Bits frei zum taggen. 31 Bit vorzeichenbehaftete Integer
		werden in der V8 durch die Tags von Zeigern unterschieden.
		Ein Integer sieht wie folgt aus: XXXX...XXX0. (X ist hierbei beliebig)
		Ein Zeiger sieht dann so aus: XXXX....XX01.
		Damit sind gerade Datenworte automatisch Integer und müssen nur noch um 1 Bit nach rechts geshiftet werden. Zeiger sind ungerade und werden noch mit 1 subtrahiert, um die tatsächliche
		Adresse zu erhalten. Dies bringt einen enormen Geschwindigkeitsvorteil.
		In der V8 gibt es für jedes Objekt 3 Datenworte. Zunächst ein Zeiger auf eine Hidden Class, ein Zeiger auf Attribute die durch Namen wie
		'x', 'y' und 'z' gekennzeichnet sind, sowie einen Zeiger auf Elemente, die durch Zahlen benannt sind. Für die letzten Beiden gibt es 2 Zustände. Im schnellen Fall zeigt der Zeiger auf
		ein Array, im Langsamen auf ein Dictionary bzw. eine Hashmap.
		
		
		Hidden Classes und Hidden Class Transitions
		Das Ziel von Hidden Classes ist es JavaScript statisch und klassenbasiert, wie Java oder C++, zu realisieren. In Java oder C++ ist das Layout der Objekte zur Kompilezeit bekannt, Eigenschaften
		und Methoden können einfach referenziert werden, da sie immer an der gleichen Stelle gespeichert sind. Bei JavaScript gibt es keine Klassen und es muss immer ein dynamischer Lookup gemacht werden, der
		im Objekt und dessen Prototypen-Kette nach dem Attribut oder der Methode sucht.
		Die Hidden Classes sollen nun die Möglichkeit geben, bekannte Techniken aus statisch, klassenbasierten Sprachen zu nutzen und Objekte mit gleicher Struktur zu gruppieren. Der Benutzer soll
		davon allerdings nichts merken.
		Wie funktionieren Hidden Classes?
		Zunächst einmal ein kleines Codestück:
		    1 function Punkt(x, y){
    2   this.x = x;
    3   this.y = y;
    4 }
		Für ein Punktobjekt gibt es nun immer 3 Datenworte. Zunächst ein Zeiger auf die initiale Klasse Class 0. Und 2 Zeiger für die Attribute des Objekts, die auf zwei
		kleine Speicherbereiche verweisen. (In diesem Fall nur der für die Attribute eingezeichnet)
		
		Nach dem Ausführen von this.x = x entsteht eine Kopie der Class 0. Der Hidden Class Zeiger des Punktobjekts wird zudem auf diese Kopie Class 1
		geändert. In dieser Class 1 wird der Offset für das x und im Speicherbereich des Punktobjekts an entsprechender Stelle gespeichert. Als letztes wird noch
		eine sogenannte "Hidden Class Transition" erzeugt, die von der Class 0 auf die Class 1 zeigt. Dieser Übergang wird benutzt, wenn ein Objekt auf die initiale
		Klasse zeigt und ein x-Attribut zum Objekt hinzugefügt wird.
		
		Nun wird noch this.y = y ausgeführt. Hierdurch entsteht eine Kopie von Class 1. Auch der Hidden Class Zeiger wird auf diese Kopie Class 2
		geändert. Der Offset in diesem Fall für y ist 1 und wird in der Hidden Class, sowie der enstprechende Wert im Speicherbereich des Objekts, gespeichert. Genau wie beim
		ersten Attribut wird wieder eine "Hidden Class Transition" auf die Class 2 erzeugt. In diesem Fall ist der Übergang von Class 1 nach Class 2, wenn
		dem Objekt ein y-Attribut hinzugefügt wird.
		
		Abschließend
		Würde ein zweites Objekt zunächst ein y-Attribut und dann ein x-Attribut hinzugefügt bekommen, entstehen 2 neue Hidden Classes, da die Zwischenstationen
		und Übergänge nicht denen des anderen Objekts ähneln.
		Diese Technik bringt einen großen Geschwindigkeitsschub, da der Zugriff auf Attribute deutlich höher ist und nicht soviele Hidden Classes für gleiche Objekte erzeugt werden müssen.
		Gerade in einem Codeblock sind meißt Objekte mit identischer Struktur. Dadurch können nun Techniken aus statisch, klassenbasierten Sprachen genutzt werden.
		
		
		Generierung von nativem Maschinencode mit Inline Caching
		In der V8 wird zunächst der komplette Code in nativen Maschinencode übersetzt. Zur Laufzeit werden dann die Zugriffe auf Attribute und Funktionsaufrufe durch Inline-Caching beschleunigt.
		Hierbei wird erstmal ein vollständiger Suchvorgang durchgeführt. Danach sind die Hidden Class und Ort von Attribut bzw. Methode bekannt. Darauf aufbauend generiert die V8 Maschinencode,
		der für zukünftige Objekte an gleicher Stelle im Code annimmt, dass sie dieselbe Hidden Class besitzen wie zuvor. Wenn dies der Fall ist, können die Eigenschaften direkt geladen werden,
		ohne einen langen Suchvorgang durchzuführen. Wenn die Annahme nicht zutrifft, wird der generierte Code entfernt und nach einem erneuten Suchvorgang durch ein neues Stück generierten
		Code ersetzt.
		Dieser Vorgang erfolgt im monomorphen Zustand. Im megamorphen Zustand werden mehrere generierte Codestücke zur Hilfe genommen, mit dessen Hilfe die V8 schnell entscheiden kann, wo die Attribute
		und Methoden liegen.
		Inline-Caching Zustände
		
			- Uninitialisiert: In diesem Zustand beginnt jede Anwendung. Es wurden bisher keine Objekte gesehen.
 
			- Monomorph: Es wurde bereits ein Objekt bzw. eine Hidden Class gesehen. Außerdem existiert ein Übergang von Uninitialisiert nach Monomorph.
 
			- Megamorph: Es wurden bereits mehrere Objekte und Hidden Classes gesehen. Dafür wird nun ein Cache von generierten Codestücken genutzt, um die Attribute und Methoden zu finden
 
		
		
		
		Speichermanagement System
		Durch die Hidden Classes und das Inline Caching mit Generierung von Maschinencode ist die V8 bereits in der Lage schnellen Zugriff auf
		Attribute und Methoden zu gewähren. Sie soll aber auch in der Lage sein, von dem megamorphen Zustand wieder in den monomorphen Zustand zu gelangen. Dazu muss es möglich sein, generierte
		Codestücke wieder wegzuwerfen. Hier kommt der Garbage Collector der V8 zum Einsatz.
		Der Garbage Collector (kurz GC) ist ein
		
			- Stop-the-world
 
			Der Prozess wird angehalten, damit Speicher bereinigt werden kann.
			- exakter
 
			Er weiß jederzeit, wo alle Objekte liegen.
			-  und Generationeller
 
		
		Garbage Collector.
		2 Generationen
		
			- Junge Generation
 
			In diesem kleinen, zusammenhängenden Speicher werden alle Objekte erzeugt. Wenn diese Generation voll ist, wird diese Generation bereinigt. Dies geschieht sehr oft. Da die meißten
			Objekte sehr kurzlebig sind, werden fast alle Objekte in der jungen Generation nach einer Garbage Collection gelöscht. Die Objekte die noch benötigt werden, werden in die alte Generation
			verschoben. Nur wenn die Bereinigung der jungen Generation nicht genügend Speicher liefert, wird auch die alte Generation angeschaut.
			- Alte Generation
 
			Für diese Generationen werden mehrere Stücke Speicher bereitgestellt. Unter anderem für den ausführbaren Maschinencode, einen Map Bereich für Hidden Classes und für
			große Objekte. Die alte Generation wird nur sehr selten angeschaut.
		
		Garbage-Collection-Typen
		
			- Scavenge
 
			Bei diesem Typen wird nur die junge Generation angeschaut und ist damit der Typ, der die ganze Zeit ausgeführt wird. Die durchschnittliche Unterbrechungsdauer liegt bei 2ms.
			- Full non-compacting collection
 
			Bei diesem Typ wird der sogenannte Mark-Sweep-Algorithmus ausgeführt. Dieser Algorithmus schaut sowohl in der alten, als auch der jungen, Generation alle Objekte an und markiert diejenigen, die
			entfernt werden sollen. Danach werden dann alle markierten Objekte entfernt. Allerdings verursacht dieser Algorithmus Fragmentierung, da Lücken zwischen den Objekten entstehen. Auch ist ein
			aufwändiger Algorithmus zum Finden von freien, passenden Speicherstücken notwendig. Daher wird in der Regel der folgende 'Full compacting collection'-Typ genutzt. Die durchschnittliche
			Unterbrechungsdauer bei der 'Full non-compacting collection' liegt bei 50ms.
			- Full compacting collection
 
			Hier wrd der Mark-Sweep-Compact-Algorithmus genutzt. Dieser macht dasselbe wie der Mark-Sweep-Algorithmus, kopiert danach aber die Objekte so um, dass sie in einem zusammenhängenden Bereich liegen.
			Deshalb muss die V8 auch einen exakten GC haben, damit sie alle Zeiger entsprechend verschieben kann, während das Kompaktieren vorgenommen wird. Dies kostet mehr Zeit, erspart aber die
			Entwicklung und das Ausführen eines komplexen Suchalgorithmus für freie Speicherstücke.  Die durchschnittliche Unterbrechungsdauer liegt bei 100ms.
		
		
		
		
		...  [ Seminar Programmiersprachen und virtuelle Maschinen ]  ...  [ Google's V8 ]  ...
		[ << Einführung ]  ...  [ Kürzliche Entwicklungen >> ]  ...  [ nach oben ]  ...