ART-Just-in-Time-Compiler implementieren

Die Android Runtime (ART) enthält einen Just-in-Time-Compiler (JIT) mit Code-Profiling, der die Leistung von Android-Anwendungen während der Ausführung kontinuierlich verbessert. Der JIT-Compiler ergänzt den aktuellen AOT-Compiler (Ahead-of-Time) von ART und verbessert die Laufzeitleistung, spart Speicherplatz und beschleunigt Anwendungs- und Systemupdates. Außerdem wird der AOT-Compiler verbessert, da das System bei automatischen App-Updates nicht mehr verlangsamt wird und Apps bei Over-the-Air-Updates (OTA-Updates) nicht mehr neu kompiliert werden müssen.

Obwohl JIT und AOT denselben Compiler mit ähnlichen Optimierungen verwenden, ist der generierte Code möglicherweise nicht identisch. JIT nutzt Informationen zum Laufzeittyp, kann eine bessere Inline-Einfügung vornehmen und ermöglicht die On-Stack-Ersetzung (OSR). Dadurch wird jeweils ein etwas anderer Code generiert.

JIT-Architektur

JIT-Architektur
Abbildung 1. JIT-Architektur.

JIT-Kompilierung

Die JIT-Kompilierung umfasst die folgenden Aktivitäten:

Profilbasierte Kompensation
Abbildung 2: Profilbasierte Kompilierung.
  1. Der Nutzer startet die App, wodurch ART veranlasst wird, die .dex-Datei zu laden.
    • Wenn die .oat-Datei (die AOT-Binärdatei für die .dex-Datei) verfügbar ist, wird sie von ART direkt verwendet. .oat-Dateien werden zwar regelmäßig generiert, enthalten aber nicht immer kompilierten Code (AOT-Binärdatei).
    • Wenn die Datei .oat keinen kompilierten Code enthält, führt ART die .dex-Datei über JIT und den Interpreter aus.
  2. JIT ist für jede Anwendung aktiviert, die nicht gemäß dem Kompilierungsfilter speed kompiliert wurde (mit der Meldung „So viel wie möglich aus der Anwendung kompilieren“).
  3. Die JIT-Profildaten werden in eine Datei in einem Systemverzeichnis heruntergeladen, auf das nur die Anwendung zugreifen kann.
  4. Der AOT-Kompilierungs-Daemon (dex2oat) analysiert diese Datei, um die Kompilierung zu steuern.

    JIT-Daemon
    Abbildung 3: JIT-Daemon-Aktivitäten.

Der Google Play-Dienst ist ein Beispiel für andere Anwendungen, die sich ähnlich wie freigegebene Bibliotheken verhalten.

JIT-Workflow

JIT-Architektur
Abbildung 4: JIT-Datenfluss.
  • Informationen zum Profiling werden im Codecache gespeichert und bei Arbeitsspeichermangel der Garbage Collection unterzogen.
    • Es gibt keine Garantie dafür, dass ein Snapshot, der erstellt wurde, als sich die Anwendung im Hintergrund befand, vollständige Daten enthält (d.h. alles, was per JIT-Kompilierung erstellt wurde).
    • Es wird nicht versucht, sicherzustellen, dass alles aufgezeichnet wird, da dies die Laufzeitleistung beeinträchtigen kann.
  • Methoden können drei verschiedene Status haben:
    • interpretiert (Dex-Code)
    • JIT kompiliert
    • AOT-kompiliert
    Wenn sowohl der JIT- als auch der AOT-Code vorhanden ist (z.B. aufgrund wiederholter Deoptimierungen), ist der JIT-Code zu bevorzugen.
  • Der Arbeitsspeicherbedarf für die Ausführung von JIT ohne Beeinträchtigung der Leistung der App im Vordergrund hängt von der jeweiligen App ab. Große Apps benötigen mehr Arbeitsspeicher als kleine Apps. Große Apps stabilisieren sich im Allgemeinen etwa 4 MB.

JIT-Protokollierung aktivieren

Führen Sie die folgenden Befehle aus, um die JIT-Protokollierung zu aktivieren:

adb root
adb shell stop
adb shell setprop dalvik.vm.extra-opts -verbose:jit
adb shell start

JIT deaktivieren

Führen Sie die folgenden Befehle aus, um JIT zu deaktivieren:

adb root
adb shell stop
adb shell setprop dalvik.vm.usejit false
adb shell start

Kompilierung erzwingen

Führen Sie zum Erzwingen der Kompilierung Folgendes aus:

adb shell cmd package compile

Häufige Anwendungsfälle für das Erzwingen der Kompilierung eines bestimmten Pakets:

  • Profilbasiert:
    adb shell cmd package compile -m speed-profile -f my-package
    
  • Vollständig:
    adb shell cmd package compile -m speed -f my-package
    

Gängige Anwendungsfälle für die erzwungene Kompilierung aller Pakete:

  • Profilbasiert:
    adb shell cmd package compile -m speed-profile -f -a
    
  • Vollständig:
    adb shell cmd package compile -m speed -f -a
    

Profildaten löschen

Android 13 oder niedriger

Führen Sie den folgenden Befehl aus, um lokale Profildaten zu löschen und kompilierten Code zu entfernen:

adb shell pm compile --reset 

Android 14 oder höher

So löschen Sie nur lokale Profildaten:

adb shell pm art clear-app-profiles 

Hinweis: Im Gegensatz zum Befehl für Android 13 oder niedriger werden mit diesem Befehl keine externen Profildaten (.dm) gelöscht, die mit der App installiert wurden.

Wenn Sie lokale Profildaten löschen und aus lokalen Profildaten generierten kompilierten Code entfernen möchten (d.h. den Installationsstatus zurücksetzen), führen Sie Folgendes aus:

adb shell pm compile --reset 

Hinweis: Dieser Befehl entfernt nicht den kompilierten Code, der aus externen Profildaten (`.dm`) generiert wurde, die mit der App installiert wurden.

Führen Sie den folgenden Befehl aus, um den gesamten kompilierten Code zu löschen:

adb shell cmd package compile -m verify -f 

Hinweis: Durch diesen Befehl bleiben lokale Profildaten erhalten.