Was macht ein Just-in-Time-Compiler (JIT)?

Antworten:

518

Ein JIT-Compiler wird ausgeführt, nachdem das Programm gestartet wurde, und kompiliert den Code (normalerweise Bytecode oder eine Art von VM-Anweisungen) im laufenden Betrieb (oder Just-in-Time, wie er genannt wird) in eine Form, die normalerweise schneller ist, normalerweise die native CPU der Host-CPU Befehlssatz. Eine JIT hat Zugriff auf dynamische Laufzeitinformationen, während ein Standard-Compiler dies nicht tut und bessere Optimierungen wie häufig verwendete Inlining-Funktionen vornehmen kann.

Dies steht im Gegensatz zu einem herkömmlichen Compiler, der den gesamten Code in Maschinensprache kompiliert, bevor das Programm zum ersten Mal ausgeführt wird.

Um es zu paraphrasieren: Konventionelle Compiler erstellen das gesamte Programm als EXE-Datei, bevor Sie es zum ersten Mal ausführen. Bei neueren Programmen wird eine Assembly mit Pseudocode (P-Code) generiert. Erst nachdem Sie das Programm auf dem Betriebssystem ausgeführt haben (z. B. durch Doppelklicken auf das entsprechende Symbol), wird der (JIT) -Compiler aktiviert und generiert Maschinencode (M-Code), den der Intel-basierte Prozessor oder was auch immer verstehen wird.

Mark Cidade
quelle
16
Und im Gegensatz zu interpretiertem Code werden die Bytecode- oder VM-Anweisungen sofort und ohne Verzögerung ausgeführt, die Anweisungen werden jedoch langsamer als in der Maschinensprache ausgeführt.
Aaron
3
Eine JIT wird häufig mit interpretiertem Code verwendet, um sie in Maschinensprache zu konvertieren, aber ja, rein interpretierter Code (ohne JITting) ist langsam. Selbst Java-Bytecode ohne JITter ist sehr langsam.
Mark Cidade
48
Das Ziel muss jedoch kein Maschinencode sein. JRuby verfügt über einen JIT-Compiler, der Ruby-Quellcode nach einigen Aufrufen in Java-Bytecode kompiliert. Nach einigen weiteren Aufrufen wird der JVM-JIT-Compiler aktiviert und kompiliert den Bytecode in nativen Code.
Jörg W Mittag
4
Es ist erwähnenswert, dass JIT, wie von Jörg angedeutet, nicht unbedingt sofort aufgerufen wird. Oft wird Code interpretiert, bis festgestellt wird, dass es sich lohnt, JITting durchzuführen. Da JITting zu Verzögerungen führen kann, kann es schneller sein, Code NICHT zu JITEN, wenn er selten verwendet wird. Daher ist eine schnelle Reaktion wichtiger als die Gesamtlaufzeit.
Adam Jaskiewicz
3
@ErikReppen: Wenn eine neue Maschine herauskommt, führt das Kompilieren und Optimieren eines Programms für diese neue Maschine unter Verwendung eines herkömmlichen Compilers wahrscheinlich schneller zu Ergebnissen als eine JIT. Auf der anderen Seite kann eine JIT, die für diese neue Maschine optimiert wurde, die Leistung von Code optimieren, der vor der Erfindung dieser neuen Maschine veröffentlicht wurde .
Supercat
255

Am Anfang war ein Compiler dafür verantwortlich, eine Hochsprache (definiert als höhere Ebene 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.

Craig Trader
quelle
5
Dieser Satz "Ein Just-In-Time-Compiler (JIT) ist ein Merkmal des Laufzeitinterpreters" sorgt jedoch für Verwirrung. zB - stackoverflow.com/questions/16439512/…
Stephen C
11
Tatsächlich war das JIT ein Add-On, und Sie können es weiterhin mit dem Parameter -Xint für Java deaktivieren, es ist also nur eine Funktion.
Craig Trader
3
Ich stimme nicht ganz zu. JIT ist keine Evolution - es ist eine Alternative zu klassischen Compilern.
i486
1
JIT ist ein Schritt auf dem Weg von der Verkabelung mechanischer Schalter zur Angabe von Suchkriterien, indem Sie Ihrem Smartphone "OK Google" sagen. Die aktuelle JIT, die als Teil von Java 7/8 verfügbar ist, geht sprunghaft über das hinaus, was als Teil von Java 2 verfügbar war - das ist auch Evolution.
Craig Trader
1
@ i486 - Sun / Oracle (AFAIK) haben noch nie einen klassischen Compiler ("vorzeitig") für Java ausgeliefert, der nativen Code generiert. Es ist eine Strecke zu argumentieren, dass JIT eine Alternative ist ... wenn sie angeblich eine Alternative sind, wurde sie nie ausgeliefert. (Ich rabattiere den GCJ AOT-Compiler, weil das nichts mit Sun / Oracle zu tun hatte und es auch keine vollständige Lösung war. Es ist jetzt sicherlich nicht realisierbar.)
Stephen C
69

JIT-Just in time sagt das Wort selbst, wann es gebraucht wird (auf Anfrage)

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 Belastung der 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.

JIT-Beispiele:

  1. In Java ist JIT in JVM (Java Virtual Machine)
  2. In C # ist es in CLR (Common Language Runtime)
  3. In Android ist es in DVM (Dalvik Virtual Machine) oder ART (Android RunTime) in neueren Versionen.
Durai Amuthan.H
quelle
7
JIT bietet einige besondere Vorteile in Frameworks mit Unterstützung für echte generische Typen. Es ist möglich, eine generische Methode zu definieren, die in der Lage ist, einen unbegrenzten Bereich von Typen zu erzeugen. Jeder von ihnen würde einen anderen Maschinencode erfordern, aber nur die JIT generiert Code für Typen, die tatsächlich erzeugt werden. Im Gegensatz dazu ist es in C ++ erforderlich, dass der Compiler Code für alle Typen generiert, die ein Programm jemals verwenden wird.
Supercat
6
Die JVM gibt beim ersten Ausführen keinen JIT-Code aus. Die ersten Male interpretiert es Bytecode. Wenn dieser Code dann oft genug ausgeführt wird, kann er sich entscheiden, ihn zu stören.
Ninjalj
1
Sie sagen, JIT in Java ist JVM. Wir stellen JVM jedoch bereits den kompilierten Code zur Verfügung, nicht wahr? Dann kompiliert es es wieder, meinst du?
Koray Tugay
@KorayTugay - Wir stellen JVM Bytecodes zur Verfügung, und JVM konvertiert einen Teil davon bei Bedarf in Maschinencode. So werden Ressourcen gespart.
Durai Amuthan.H
1
In Java ist JIT keine JVM. Es ist nur ein Teil davon.
Happs
25

Wie andere schon erwähnt haben

JIT steht für Just-in-Time, was bedeutet, dass Code bei Bedarf kompiliert wird und nicht vor der Laufzeit.

Um der obigen Diskussion einen Punkt hinzuzufügen, zählt JVM, wie oft eine Funktion ausgeführt wird. Wenn diese Anzahl einen vordefinierten Grenzwert überschreitet, kompiliert JIT den Code in eine 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 - der Interpreter interpretiert 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.

Aniket Thakur
quelle
14

Der JIT-Compiler kompiliert den Bytecode nur bei der ersten Ausführung zu äquivalentem nativem Code. Bei jeder aufeinanderfolgenden Ausführung verwendet die JVM lediglich den bereits kompilierten nativen Code, um die Leistung zu optimieren.

Geben Sie hier die Bildbeschreibung ein

Ohne JIT-Compiler übersetzt der JVM-Interpreter den Bytecode zeilenweise, sodass er so aussieht, als würde eine native Anwendung ausgeführt.

Geben Sie hier die Bildbeschreibung ein

Quelle


quelle
1
Meine Interpretation von JIT ist, dass es sich wie eine Memoisierung verhält, bei der häufig verwendete Funktionen "gespeichert" werden und die Kosten für die Kompilierung von Java-Bytecode zu nativem ISA-abhängigem Code umgangen werden. Wenn dies korrekt ist, warum wird Java nicht von Anfang an vollständig in nativen Code kompiliert? Dies würde jede Art von Laufzeitkompilierung reduzieren und Java auf dem Computer "nativ" machen?
Michael Choi
12

JIT steht für Just-in-Time, was bedeutet, dass Code bei Bedarf kompiliert wird und nicht vor der Laufzeit.

Dies ist vorteilhaft, da der Compiler Code generieren kann, der für Ihren bestimmten Computer optimiert ist. Ein statischer Compiler kompiliert wie ein durchschnittlicher C-Compiler den gesamten Code in ausführbaren Code auf dem Computer des Entwicklers. Daher führt der Compiler basierend auf einigen Annahmen Optimierungen durch. Es kann langsamer kompilieren und mehr Optimierungen vornehmen, da es die Ausführung des Programms für den Benutzer nicht verlangsamt.

Brian Lyttle
quelle
Warum werden kompilierte Codes nicht irgendwo auf dem Computer des Benutzers gespeichert, sodass JIT sie beim nächsten Ausführen der Anwendung nicht erneut kompilieren muss?
Omerfarukdogan
Gute Beobachtungen. Dies ist möglich, aber ob es tatsächlich von Vorteil ist, hängt von der Plattform und der Nutzung der App ab. Die JIT-Optimierung ist nicht unbedingt mit der Offline-Optimierung oder der vorzeitigen Optimierung identisch, sodass der Vorteil möglicherweise nur "nicht JITting" ist, was möglicherweise viel hilft oder nicht.
Brian Lyttle
9

Nachdem der Bytecode (der architekturneutral ist) vom Java-Compiler generiert wurde, wird die Ausführung von der JVM (in Java) übernommen. Der Bytecode wird vom Loader in JVM geladen, und dann wird jeder Bytebefehl interpretiert.

Wenn wir eine Methode mehrmals aufrufen müssen, müssen wir denselben Code viele Male interpretieren. Dies kann länger dauern als erforderlich. Wir haben also die JIT-Compiler (Just-in-Time). Wenn das Byte in JVM (seine Laufzeit) geladen wurde, wird der gesamte Code kompiliert und nicht interpretiert, wodurch Zeit gespart wird.

JIT-Compiler funktionieren nur zur Laufzeit, daher haben wir keine Binärausgabe.

Benutzer
quelle
2
Der gesamte Code wird beim Laden in die JVM nicht kompiliert, da nur wenige Informationen (siehe Anleitung) zum Kompilieren vorhanden sind. Denken Sie daran, dass Leistung das ultimative Ziel ist. JIT ist ziemlich selektiv: Überwachung und Auswahl der beliebtesten Optimierungsmethoden. Und das so lange, bis das maximale Optimierungsniveau für einzelne Methoden erreicht ist.
Yaw Boakye
7

Just In Time Compiler (JIT):
Kompiliert die Java-Bytecodes in Maschinenanweisungen dieser bestimmten CPU.

Zum Beispiel, wenn wir eine Schleifenanweisung in unserem Java-Code haben:

while(i<10){
    // ...
    a=a+i;
    // ...
 }

Der obige Schleifencode wird 10 Mal ausgeführt, wenn der Wert von i 0 ist.

Es ist nicht erforderlich, den Bytecode immer wieder zehnmal zu kompilieren, da derselbe Befehl zehnmal ausgeführt wird. In diesem Fall muss dieser Code nur einmal kompiliert werden, und der Wert kann für die erforderliche Anzahl von Malen geändert werden. Der Just In Time (JIT) -Compiler verfolgt solche Anweisungen und Methoden (wie oben erwähnt) und kompiliert solche Bytecodeteile zu Maschinencode, um eine bessere Leistung zu erzielen.

Ein anderes ähnliches Beispiel ist die Suche nach einem Muster unter Verwendung von "Regulärer Ausdruck" in einer Liste von Zeichenfolgen / Sätzen.

JIT Compiler kompiliert nicht den gesamten Code in Maschinencode. Es kompiliert Code, der zur Laufzeit ein ähnliches Muster aufweist.

Weitere Informationen finden Sie in dieser Oracle-Dokumentation zu JIT verstehen .

Anands23
quelle
"Es ist nicht notwendig, den Bytecode immer wieder zehnmal zu kompilieren, da derselbe Befehl zehnmal ausgeführt wird" - was ist mit einem regulären Compiler? Kompiliert es dieses Stück mehrmals?
TT_
4

Sie haben Code, der in eine IL (Zwischensprache) kompiliert ist. Wenn Sie Ihr Programm ausführen, versteht der Computer diesen Code nicht. Es versteht nur nativen Code. Der JIT-Compiler kompiliert Ihre IL also im laufenden Betrieb in nativen Code. Dies geschieht auf Methodenebene.

Charles Graham
quelle
2
Was meinst du mit "Methodenebene"?
Koray Tugay
4

Ich weiß, dass dies ein alter Thread ist, aber die Laufzeitoptimierung ist ein weiterer wichtiger Teil der JIT-Kompilierung, der hier anscheinend nicht behandelt wird. Grundsätzlich kann der JIT-Compiler das laufende Programm überwachen, um Möglichkeiten zur Verbesserung der Ausführung zu ermitteln. Dann kann es diese Änderungen im laufenden Betrieb vornehmen - zur Laufzeit. Google JIT-Optimierung (javaworld hat einen ziemlich guten Artikel darüber. )

eze
quelle
3

Ein Just-in-Time-Compiler (JIT) ist eine Software, die eine nicht ausführbare Eingabe empfängt und den entsprechenden auszuführenden Maschinencode zurückgibt. Zum Beispiel:

Intermediate representation    JIT    Native machine code for the current CPU architecture

     Java bytecode            --->        machine code
     Javascript (run with V8) --->        machine code

Dies hat zur Folge, dass für eine bestimmte CPU-Architektur der entsprechende JIT-Compiler installiert werden muss.

Differenz-Compiler, Interpreter und JIT

Obwohl es im Allgemeinen Ausnahmen geben kann, wenn wir Quellcode in Maschinencode umwandeln möchten, können wir Folgendes verwenden:

  1. Compiler : Nimmt den Quellcode und gibt eine ausführbare Datei zurück
  2. Interpreter : Führt die Programmanweisung nach Anweisung aus. Es nimmt ein ausführbares Segment des Quellcodes und wandelt dieses Segment in Maschinenanweisungen um. Dieser Vorgang wird wiederholt, bis der gesamte Quellcode in Maschinenanweisungen umgewandelt und ausgeführt wurde.
  3. JIT : Viele verschiedene Implementierungen einer JIT sind möglich, eine JIT ist jedoch normalerweise eine Kombination aus einem Compliler und einem Interpreter. Die JIT wandelt zunächst Zwischendaten (z. B. Java-Bytecode) um, die sie durch Interpretation in Maschinensprache empfängt. Eine JIT kann häufig erkennen, wann ein bestimmter Teil des Codes häufig ausgeführt wird, und der kompiliert diesen Teil für eine schnellere Ausführung.
Willem van der Veen
quelle
2

Jit steht für Just-in-Time-Compiler. Jit ist ein Programm, das Java-Bytecode in Anweisungen umwandelt, die direkt an den Prozessor gesendet werden können.

Wenn Sie den Java-Just-in-Time-Compiler (eigentlich einen zweiten Compiler) auf der jeweiligen Systemplattform verwenden, wird der Bytecode in einen bestimmten Systemcode umgewandelt. Sobald der Code vom JIT-Complier neu kompiliert wurde, wird er normalerweise schneller auf dem Computer ausgeführt.

Der Just-in-Time-Compiler wird mit der virtuellen Maschine geliefert und optional verwendet. Es kompiliert den Bytecode in plattformspezifischen ausführbaren Code, der sofort ausgeführt wird.

user3459027
quelle
2

Die Just-in-Time-Kompilierung (JIT) (auch dynamische Übersetzung oder Laufzeitkompilierung) ist eine Methode zum Ausführen von Computercode , bei der die Kompilierung während der Ausführung eines Programms - zur Laufzeit - und nicht vor der Ausführung erfolgt .

Die IT-Kompilierung ist eine Kombination der beiden traditionellen Ansätze zur Übersetzung in Maschinencode - AOT (Pre-of-Time Compilation) und Interpretation - und kombiniert einige Vor- und Nachteile beider. Die JIT-Kompilierung kombiniert die Geschwindigkeit des kompilierten Codes mit der Flexibilität der Interpretation .

Betrachten wir die in JVM verwendete JIT.

Beispielsweise generieren die HotSpot JVM JIT-Compiler dynamische Optimierungen. Mit anderen Worten, sie treffen Optimierungsentscheidungen, während die Java-Anwendung ausgeführt wird, und generieren leistungsstarke native Maschinenanweisungen, die auf die zugrunde liegende Systemarchitektur ausgerichtet sind.

Wenn eine Methode zum Kompilieren ausgewählt wird, gibt die JVM ihren Bytecode an den Just-In-Time-Compiler (JIT) weiter. Die JIT muss die Semantik und Syntax des Bytecodes verstehen, bevor sie die Methode korrekt kompilieren kann. Um dem JIT-Compiler bei der Analyse der Methode zu helfen, wird sein Bytecode zunächst in einer internen Darstellung neu formuliert, die als Trace-Bäume bezeichnet wird und dem Maschinencode ähnlicher ist als dem Bytecode. An den Bäumen der Methode werden dann Analysen und Optimierungen durchgeführt. Am Ende werden die Bäume in nativen Code übersetzt.

Ein Trace-Baum ist eine Datenstruktur, die bei der Laufzeitkompilierung von Programmcode verwendet wird. Ablaufverfolgungsbäume werden in einer Art "Just-in-Time-Compiler" verwendet, der den während Hotspots ausgeführten Code nachverfolgt und kompiliert. Verweisen Sie darauf .

Verweisen :

Prime
quelle
1

Ein Nicht-JIT-Compiler nimmt den Quellcode und wandelt ihn zur Kompilierungszeit in maschinenspezifischen Bytecode um. Ein JIT-Compiler verwendet maschinenunabhängigen Bytecode, der zur Kompilierungszeit generiert wurde, und wandelt ihn zur Laufzeit in maschinenspezifischen Bytecode um. Der von Java verwendete JIT-Compiler ermöglicht es einer einzelnen Binärdatei, ohne Änderungen auf einer Vielzahl von Plattformen ausgeführt zu werden.


quelle
0

20% des Bytecodes werden 80% der Zeit verwendet. Der JIT-Compiler erhält diese Statistiken und optimiert diese 20% des Bytecodes, um schneller ausgeführt zu werden, indem er Inline-Methoden hinzufügt, nicht verwendete Sperren entfernt usw. und den für diesen Computer spezifischen Bytecode erstellt. Ich zitiere aus diesem Artikel, ich fand es praktisch. http://java.dzone.com/articles/just-time-compiler-jit-hotspot

Santosh Budhe
quelle
Ich bin mir nicht sicher, warum dies mit -1 markiert wurde. Ich denke, der Punkt hier ist, dass Laufzeitstatistiken verwendet werden, um die Optimierung zu unterstützen.
Eze
Ja, aber die Antwort hat es nicht so formuliert. Im wahrsten Sinne des Wortes optimiert JIT nicht die heißesten 20% des Codes.
Mabraham
0

JIT bezieht sich in einigen JVM-Implementierungen auf die Ausführungs-Engine. Eine, die schneller ist, aber mehr Speicher benötigt, ist ein Just-in-Time-Compiler. In diesem Schema werden die Bytecodes einer Methode beim ersten Aufruf der Methode zu nativem Maschinencode kompiliert. Der native Maschinencode für die Methode wird dann zwischengespeichert, sodass er beim nächsten Aufruf derselben Methode wiederverwendet werden kann.

Venkata Santhosh Piduri
quelle
2
Ich würde es vermeiden, solche Fragen zu beantworten, wenn Sie nichts Neues / Besseres anbieten. Wenn Sie eine Reaktion erhalten, ist dies wahrscheinlich eine Ablehnung oder Kritik: Ihre Antwort ist ungenau. "JIT" ist nicht auf eine Java Virtual Machine beschränkt , "schneller, verbraucht aber mehr Speicher" ist ein wahrscheinlicher Effekt, der dem JIT-Konzept jedoch nicht eigen ist, und Methoden werden häufig nicht beim ersten Aufruf kompiliert, sondern nach mehreren, wenn klar wird, dass dies der Fall ist Die Zeit für JIT'ing ist insgesamt vorteilhaft.
Zapl
0

JVM führt aus Leistungsgründen zur Laufzeit Kompilierungsschritte aus. Dies bedeutet, dass Java keine saubere Trennung zwischen Kompilierung und Ausführung aufweist. Zunächst wird eine sogenannte statische Kompilierung vom Java-Quellcode zum Bytecode durchgeführt. Dieser Bytecode wird dann zur Ausführung an die JVM übergeben. Die Ausführung von Bytecode ist jedoch langsam, sodass die JVM misst, wie oft der Bytecode ausgeführt wird, und wenn sie einen "Hotspot" von Code erkennt, der sehr häufig ausgeführt wird, führt sie eine dynamische Kompilierung von Bytecode zu Maschinencode des "Hotspot" -Codes (Hotspot-Profiler) durch. So effektiv werden Java-Programme heute durch Maschinencode-Ausführung ausgeführt.

hi.nitish
quelle
0

Der Just In Time-Compiler, auch als JIT-Compiler bekannt, wird zur Leistungsverbesserung in Java verwendet. Es ist standardmäßig aktiviert. Die Kompilierung erfolgt zur Ausführungszeit eher früher. Java hat die Verwendung des JIT-Compilers durch die Aufnahme in JVM populär gemacht.

Ganesh Giri
quelle