Wdrażanie kompilatora ART just-in-time

Środowisko wykonawcze Androida (ART) zawiera kompilator JIT (just-in-time) z profilowaniem kodu, który stale zwiększa wydajność aplikacji na Androida podczas ich działania. Kompilator JIT uzupełnia obecny kompilator AOT (ahead-of-time) środowiska ART i zwiększa wydajność środowiska wykonawczego, oszczędza miejsce na dane oraz przyspiesza aktualizacje aplikacji i systemu. Ulepsza też kompilator AOT, ponieważ nie powoduje spowolnienia systemu podczas automatycznych aktualizacji aplikacji ani ponownej kompilacji aplikacji podczas aktualizacji bezprzewodowych (OTA).

Chociaż kompilatory JIT i AOT używają tego samego kompilatora z podobnym zestawem optymalizacji, wygenerowany kod może nie być identyczny. JIT korzysta z informacji o typach w czasie działania, może lepiej wstawiać kod w miejscu wywołania i umożliwia kompilację z zamianą na stosie (OSR), co generuje nieco inny kod.

Architektura JIT

Architektura JIT
Rysunek 1. architekturę JIT,

kompilacja JIT

Kompilacja JIT obejmuje te działania:

Kompilacja z optymalizacją na podstawie profilu
Rysunek 2. kompilacja z użyciem profilu
.
  1. Użytkownik uruchamia aplikację, co powoduje, że ART wczytuje plik .dex.
    • Jeśli plik .oat (binarny AOT dla pliku .dex) jest dostępny, ART używa go bezpośrednio. Chociaż pliki .oat są generowane regularnie, nie zawsze zawierają skompilowany kod (binarny AOT).
    • Jeśli plik .oat nie zawiera skompilowanego kodu, ART uruchamia go za pomocą kompilatora JIT i interpretera..dex
  2. Kompilacja JIT jest włączona w przypadku każdej aplikacji, która nie jest kompilowana zgodnie z speed filtrem kompilacji (który mówi „skompiluj jak najwięcej z aplikacji”).
  3. Dane profilu JIT są zapisywane w pliku w katalogu systemowym, do którego dostęp ma tylko aplikacja.
  4. Demon kompilacji AOT (dex2oat) analizuje ten plik, aby sterować kompilacją.

    Demon JIT
    Rysunek 3. działania demona JIT;

Usługa Google Play jest przykładem używanym przez inne aplikacje, które działają podobnie do bibliotek współdzielonych.

Przepływ pracy JIT

Architektura JIT
Rysunek 4. przepływ danych JIT.
  • Informacje profilowe są przechowywane w pamięci podręcznej kodu i podlegają odśmiecaniu w przypadku braku pamięci.
    • Nie ma gwarancji, że zrzut wykonany, gdy aplikacja działała w tle, będzie zawierać pełne dane (czyli wszystko, co zostało skompilowane JIT).
    • Nie ma próby zapewnienia, że wszystko zostanie zarejestrowane (ponieważ może to wpłynąć na wydajność w czasie działania).
  • Metody mogą mieć 3 różne stany:
    • interpretowany (kod DEX)
    • skompilowany JIT,
    • Skompilowane AOT
    Jeśli istnieją zarówno kod JIT, jak i AOT (np. z powodu wielokrotnych deoptymalizacji), preferowany jest kod JIT.
  • Wymagania dotyczące pamięci potrzebnej do uruchomienia kompilacji JIT bez wpływu na wydajność aplikacji na pierwszym planie zależą od konkretnej aplikacji. Duże aplikacje wymagają więcej pamięci niż małe. Zwykle duże aplikacje stabilizują się na poziomie około 4 MB.

Włączanie logowania JIT

Aby włączyć rejestrowanie JIT, uruchom te polecenia:

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

Wyłączanie JIT

Aby wyłączyć JIT, uruchom te polecenia:

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

Wymuś kompilację

Aby wymusić kompilację, uruchom to polecenie:

adb shell cmd package compile

Typowe przypadki użycia wymuszonego kompilowania konkretnego pakietu:

  • Na podstawie profilu:
    adb shell cmd package compile -m speed-profile -f my-package
    
  • Pełna:
    adb shell cmd package compile -m speed -f my-package
    

Typowe przypadki użycia wymuszonego kompilowania wszystkich pakietów:

  • Na podstawie profilu:
    adb shell cmd package compile -m speed-profile -f -a
    
  • Pełna:
    adb shell cmd package compile -m speed -f -a
    

Usuwanie danych z profilu

Android 13 lub starszy

Aby wyczyścić lokalne dane profilu i usunąć skompilowany kod, uruchom to polecenie:

adb shell pm compile --reset 

Android 14 lub nowszy

Aby wyczyścić tylko lokalne dane profilu:

adb shell pm art clear-app-profiles 

Uwaga: w przeciwieństwie do polecenia dla Androida 13 lub starszego to polecenie nie usuwa danych profilu zewnętrznego (`.dm`) zainstalowanych z aplikacją.

Aby wyczyścić dane profilu lokalnego i usunąć skompilowany kod wygenerowany na podstawie danych profilu lokalnego (czyli przywrócić stan instalacji), wykonaj to działanie:

adb shell pm compile --reset 

Uwaga: to polecenie nie usuwa skompilowanego kodu wygenerowanego na podstawie danych profilu zewnętrznego (`.dm`) zainstalowanego z aplikacją.

Aby usunąć cały skompilowany kod, uruchom to polecenie:

adb shell cmd package compile -m verify -f 

Uwaga: to polecenie zachowuje lokalne dane profilu.