Just in Time Compilation erklärt

Die Just-in-Time-Kompilierung ist eine Methode zur Verbesserung der Leistung interpretierter Programme. Während der Ausführung kann das Programm in nativen Code kompiliert werden, um seine Leistung zu verbessern. Es wird auch als dynamische Kompilierung bezeichnet.

Die dynamische Kompilierung hat einige Vorteile gegenüber der statischen Kompilierung. Beim Ausführen von Java- oder C # -Anwendungen kann die Laufzeitumgebung die Anwendung während der Ausführung profilieren. Dadurch kann optimierter Code generiert werden. Wenn sich das Verhalten der Anwendung während der Ausführung ändert, kann die Laufzeitumgebung den Code neu kompilieren.

Einige der Nachteile sind Startverzögerungen und der Aufwand für die Kompilierung zur Laufzeit. Um den Overhead zu begrenzen, kompilieren viele JIT-Compiler nur die häufig verwendeten Codepfade.

Überblick

Traditionell gibt es zwei Methoden zum Konvertieren von Quellcode in ein Formular, das auf einer Plattform ausgeführt werden kann. Die statische Kompilierung konvertiert den Code in eine Sprache für eine bestimmte Plattform. Ein Interpreter führt den Quellcode direkt aus.

Die JIT-Kompilierung versucht, die Vorteile beider zu nutzen. Während das interpretierte Programm ausgeführt wird, ermittelt der JIT-Compiler den am häufigsten verwendeten Code und kompiliert ihn zu Maschinencode. Dies kann je nach Compiler mit einer Methode oder einem kleineren Codeabschnitt erfolgen.

Die dynamische Zusammenstellung wurde erstmals 1960 in einem Artikel von J. McCarthy über LISP beschrieben.

Just In Time Compilation, JIT oder Dynamic Translation ist eine Kompilierung, die während der Ausführung eines Programms durchgeführt wird. Das heißt, zur Laufzeit im Gegensatz zu vor der Ausführung. Was passiert, ist die Übersetzung in Maschinencode. Die Vorteile einer JIT liegen in der Tatsache begründet, dass ein JIT-Compiler, da die Kompilierung zur Laufzeit erfolgt, Zugriff auf dynamische Laufzeitinformationen hat, um bessere Optimierungen (z. B. Inlining-Funktionen) vornehmen zu können.

Was für die JIT-Kompilierung wichtig ist, ist, dass der Bytecode in Maschinencode-Anweisungen der laufenden Maschine kompiliert wird. Dies bedeutet, dass der resultierende Maschinencode für die CPU-Architektur der laufenden Maschine optimiert ist.

Einige Beispiele für JIT-Compiler sind JVM (Java Virtual Machine) in Java und CLR (Common Language Runtime) in C #.

Geschichte

Am Anfang war ein Compiler dafür verantwortlich, eine Hochsprache (definiert als höhere Stufe als Assembler) in Objektcode (Maschinenanweisungen) umzuwandeln, der dann (durch einen Linker) in eine ausführbare Datei verknüpft wurde.

An einem Punkt in der Entwicklung der Sprachen kompilierten Compiler eine Hochsprache in Pseudocode, der dann (von einem Interpreter) interpretiert wurde, um Ihr Programm auszuführen. Dadurch wurden der Objektcode und die ausführbaren Dateien eliminiert und diese Sprachen konnten auf mehrere Betriebssysteme und Hardwareplattformen portiert werden. Pascal (der zu P-Code kompiliert wurde) war einer der ersten; Java und C # sind neuere Beispiele. Schließlich wurde der Begriff P-Code durch Bytecode ersetzt, da die meisten Pseudooperationen ein Byte lang sind.

Ein Just-In-Time-Compiler (JIT) ist eine Funktion des Laufzeitinterpreters, der anstelle der Interpretation des Bytecodes bei jedem Aufruf einer Methode den Bytecode in die Maschinencodeanweisungen der laufenden Maschine kompiliert und diese dann aufruft Objektcode stattdessen. Im Idealfall wird durch die Effizienz beim Ausführen von Objektcode die Ineffizienz beim erneuten Kompilieren des Programms bei jeder Ausführung überwunden.

Typisches Szenario

Der Quellcode wird vollständig in Maschinencode konvertiert

JIT-Szenario

Der Quellcode wird in eine Assembler-ähnliche Struktur konvertiert [z. B. IL (Zwischensprache) für C #, ByteCode für Java].

Der Zwischencode wird nur dann in die Maschinensprache konvertiert, wenn die Anwendung die erforderlichen Codes benötigt. Die Codes werden nur in Maschinencode konvertiert.

Vergleich von JIT und Nicht-JIT

In JIT wird nicht der gesamte Code zuerst in Maschinencode konvertiert. Ein Teil des erforderlichen Codes wird in Maschinencode konvertiert. Wenn sich eine aufgerufene Methode oder Funktionalität nicht in der Maschine befindet, wird dieser in Maschinencode umgewandelt, wodurch die Belastung verringert wird die CPU. Da der Maschinencode zur Laufzeit generiert wird, erzeugt der JIT-Compiler Maschinencode, der für die Ausführung der CPU-Architektur der Maschine optimiert ist.

Einige Beispiele für JIT sind:

  • Java: JVM (Java Virtual Machine)
  • C #: CLR (Common Language Runtime)
  • Android: DVM (Dalvik Virtual Machine) oder ART (Android RunTime) in neueren Versionen

Die Java Virtual Machine (JVM) führt Bytecode aus und zählt, wie oft eine Funktion ausgeführt wird. Wenn diese Anzahl einen vordefinierten Grenzwert überschreitet, kompiliert JIT den Code in Maschinensprache, die direkt vom Prozessor ausgeführt werden kann (im Gegensatz zu dem normalen Fall, in dem javac den Code in Bytecode und dann in Java kompiliert, interpretiert der Interpreter diesen Bytecode Zeile für Zeile und konvertiert ihn in Maschinencode und wird ausgeführt).

Auch bei der nächsten Berechnung dieser Funktion wird derselbe kompilierte Code erneut ausgeführt, im Gegensatz zur normalen Interpretation, bei der der Code erneut Zeile für Zeile interpretiert wird. Dies beschleunigt die Ausführung.