Warum werden VM-Sprachen nicht nur einmal kompiliert?

8

(Zunächst sollte ich klarstellen, dass Compiler und virtuelle Maschinen (auch bekannt als ) für mich ein völlig unbekanntes Feld sind.)

So wie ich es verstehe, wird jedes Mal, wenn eine Java / C # / ... -Anwendung ausgeführt wird, eine VM aufgerufen und Zwischencode (Bytecode, CIL usw.) in Maschinenanweisungen übersetzt.

Aber warum kann dieser Vorgang nicht nur einmal ausgeführt werden - zur Installationszeit?

vemv
quelle
1
Was ist die Installationszeit?
Peter Taylor
3
Ich bin mir nicht sicher, ob es sich um einen Standardbegriff handelt, aber ich meinte: Wenn der Benutzer das Programm installiert - führt es zum ersten Mal aus -, anstatt ein Programm auf dem Computer des Entwicklers zu kompilieren (der nicht weiß, welche Plattform ein bestimmter Benutzer verwenden wird) - und Sie möchten nicht ein Installationsprogramm pro Plattform verteilen).
vemv
@vemv Kompilieren zur Laufzeit ermöglicht es der VM, die Maschinenanweisungen für Ihre spezielle Hardware zu spezialisieren
Lucina

Antworten:

8

Im Fall von Java kann die JVM Optimierungen durchführen, die Bibliotheksgrenzen überschreiten. Sie können beispielsweise eine Methode aus einer Bibliothek in Ihren eigenen Clientcode einbinden. Diese Art der Optimierung konnte zur Kompilierungszeit nicht durchgeführt werden, da sich die Bibliothek vor der Ausführung möglicherweise ändert. Es ist durchaus möglich, dass Ihr libfoo-1.0 ohne Neukompilierung durch libfoo-1.1 ersetzt wird. In diesem Fall werden bibliotheksübergreifende Inlines, die zur Kompilierungszeit erstellt wurden, vollständig ungültig.

Wenn Sie die Optimierung ausschließlich zur Laufzeit durchführen, besteht keine Sorge, dass die unter Ihnen geänderte Bibliothek die Optimierungen ungültig macht.

Steven Schlansker
quelle
1
Eine Inline könnte sein, anstatt Maschinencode zu generieren, um ein "Y.setX (x)" (wobei Y aus einer Bibliothek eines dritten Teils stammt) aufzurufen, das dann "this.x = x" ausführt und dann einfach Maschinencode für "Yx = x" generiert ".
Zusammenfassend enthält die Laufzeit Informationen, die die Kompilierungszeit nicht enthält.
Daniel Gratzer
6

Weil dies verhindert, dass sie viele Funktionen nutzen. Wie kann die JIT beispielsweise neue generische Instanziierungen aus zur Laufzeit geladenen DLLs generieren? Diese DLLs sind zur Installationszeit nicht vorhanden.

DeadMG
quelle
1
Prost auf die Antwort. Ich glaube, ich habe das Problem mit der Instanziierung - kann jedoch nicht 100% sicher sein, da Ihre Antwort etwas zu kurz ist. Auch das Auflisten anderer nicht verfügbarer Funktionen würde Ihren Standpunkt stärken.
vemv
3
Oder allgemein: Eine JIT kann Optimierungen basierend auf Eingaben vornehmen. Zur Laufzeit geladene DLLs sind eine Art von Eingabe.
Amara
1
Offensichtlich werden diese DLL als auch installiert, und jede DLL konnte zu kompiliert werden seine Installationszeit. Sie verlieren modulübergreifende Optimierungen, aber diese sind sowieso ein bisschen theoretisch.
MSalters
@MSalters: Nicht jede DLL hat eine "Installations" -Zeit.
DeadMG
@DeadMG: Wir beschäftigen uns sowieso mit hypothetischen Systemen. Ein solches System kann leicht eine Installation erfordern. (Es wäre zusätzlich ein Sicherheitsvorteil, wenn die Einführung von ausführbarem Code explizit verwaltet würde).
MSalters
5

Dies kann und ist zumindest bei .NET-Anwendungen häufig der Fall. Siehe Native Image Generator

Ein Tool, das die Leistung verwalteter Anwendungen verbessert. Ngen.exe erstellt native Images, bei denen es sich um Dateien handelt, die kompilierten prozessorspezifischen Maschinencode enthalten, und installiert sie im nativen Image-Cache auf dem lokalen Computer. Die Laufzeit kann native Images aus dem Cache verwenden, anstatt den Just-in-Time-Compiler (JIT) zum Kompilieren der ursprünglichen Assembly zu verwenden ...

Nemanja Trifunovic
quelle
Beachten Sie, dass dies auch der von Google entwickelten Android Runtime (ART) ähnelt, um die Leistung von Android Apps zu verbessern
neelsg
3

Um die Frage gemäß der Klarstellung neu zu formulieren:

Warum kann der Bytecode beim ersten Ausführen des Programms nicht zu nativem Code kompiliert werden?

Ich sehe folgende Probleme:

  • Wo würden die Ergebnisse gespeichert? Sie können nicht davon ausgehen, dass die Datei mit dem Bytecode beschreibbar ist. Sie möchten den Computer eines Entwicklers nicht aufblähen, indem Sie jedes Mal, wenn er einen Test ausführt, eine neue EXE-Datei in den permanenten Speicher verschieben. Wenn Sie die Datei im temporären Speicher speichern, geht sie beim nächsten Neustart verloren, sodass Sie nicht viel gewonnen haben.

  • Sie tauschen jedes Mal einen etwas langsamen Start gegen einen sehr langsamen Start aus. Ich werde beim Kunden keinen guten Eindruck hinterlassen.

  • Sie werden erhebliche Probleme mit dem dynamischen Laden von Klassen haben.

Peter Taylor
quelle
2
Der erste Punkt ist trivial. Caches sind recht gut verstanden. Wenn der zugrunde liegende ausführbare Bytecode entfernt wird, können Sie den zugehörigen Cache-Eintrag löschen und auch, wenn er nicht zu lange ausgeführt wird. Was den zweiten Punkt betrifft, können Sie nicht verwendete Methoden in einem Hintergrundthread kompilieren. Dies sollte die Startzeit nicht behindern, wenn Sie aufgerufene Methoden im Vordergrund kompilieren.
MSalters
Soweit ich weiß, geht es nicht um das Kompilieren beim ersten Durchlauf, sondern um das Kompilieren bei der Installation.
Nemanja Trifunovic
@NemanjaTrifunovic, lesen Sie die Kommentare zu der Frage.
Peter Taylor
1
Ich fürchte, ich habe mich nicht gut erklärt, sorry. Ich meinte das erste Mal eine Anwendung jemals lief, dann würden keine weiteren Compilations mehr benötigt werden. Genau wie wenn Sie ein C-Programm kompilieren müssen, bevor Sie es unter Linux verwenden können.
vemv
1
Ich denke, es zählt so ziemlich als Installation - diese Kompilierungen / Build-Prozesse sind bereits für Sie geschrieben.
vemv