Wdrażanie kompilatora ART just-in-time

Środowisko wykonawcze Androida (ART) zawiera kompilator JIT (just-in-time) z profilowaniem kodu, który stale poprawia wydajność aplikacji na Androida podczas ich działania. Kompilator JIT uzupełnia obecny kompilator AOT (ahead-of-time) środowiska ART i poprawia wydajność środowiska wykonawczego, oszczędza miejsce na dane i przyspiesza aktualizacje aplikacji i systemu. Poprawia też działanie kompilatora AOT, ponieważ zapobiega spowolnieniu systemu podczas automatycznych aktualizacji aplikacji lub ponownej kompilacji aplikacji podczas aktualizacji OTA (over-the-air).

Chociaż kompilatory JIT i AOT używają tego samego kompilatora z podobnym zestawem optymalizacji, wygenerowany kod może się różnić. Kompilator JIT korzysta z informacji o typach środowiska wykonawczego, może lepiej wstawiać kod i umożliwia kompilację OSR (on stack replacement), co powoduje generowanie nieco innego kodu.

Architektura JIT

Architektura JIT
Rysunek 1. Architektura JIT.

Kompilacja JIT

Kompilacja JIT obejmuje te działania:

Kompilacja z optymalizacją na podstawie profilu
Rysunek 2. Kompilacja oparta na profilu.
  1. Użytkownik uruchamia aplikację, co powoduje, że środowisko ART wczytuje plik .dex.
    • Jeśli dostępny jest plik .oat (binarny plik AOT dla pliku .dex ), środowisko ART używa go bezpośrednio. Pliki .oat są generowane regularnie, ale nie zawsze zawierają skompilowany kod (plik binarny AOT).
    • Jeśli plik .oat nie zawiera skompilowanego kodu, środowisko ART uruchamia kompilator JIT i interpreter, aby wykonać plik .dex.
  2. Kompilator JIT jest włączony w przypadku każdej aplikacji, która nie jest kompilowana zgodnie z filtrem kompilacji speed (który oznacza „skompiluj jak najwięcej kodu 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 przeprowadzić kompilację.

    Demon JIT
    Rysunek 3. Działania demona JIT.

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

Proces JIT

Architektura JIT
Rysunek 4. Przepływ danych JIT.
  • Informacje o profilowaniu są przechowywane w pamięci podręcznej kodu i podlegają odśmiecaniu w przypadku braku pamięci.
    • Nie ma gwarancji, że migawka utworzona, gdy aplikacja działała w tle, będzie zawierać pełne dane (czyli wszystkie dane, które zostały skompilowane przez JIT).
    • Nie ma też gwarancji, że wszystkie dane zostaną zarejestrowane (ponieważ może to wpłynąć na wydajność środowiska wykonawczego).
  • Metody mogą być w 3 różnych stanach:
    • interpretowane (kod dex),
    • skompilowane przez JIT,
    • skompilowane przez AOT.
    Jeśli istnieją zarówno kod JIT, jak i AOT (np. z powodu powtarzających się deoptymalizacji), preferowany jest kod skompilowany przez JIT.
  • Wymagania dotyczące pamięci do uruchomienia kompilatora JIT bez wpływu na wydajność aplikacji działającej na pierwszym planie zależą od danej 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ć logowanie 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

Wymuszanie kompilacji

Aby wymusić kompilację, uruchom to polecenie:

adb shell cmd package compile

Typowe przypadki użycia wymuszonej kompilacji konkretnego pakietu:

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

Typowe przypadki użycia wymuszonej kompilacji wszystkich pakietów:

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

Czyszczenie danych profilu

W Androidzie 13 lub starszym

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

adb shell pm compile --reset 

W Androidzie 14 lub nowszym

Aby wyczyścić tylko lokalne dane profilu:

adb shell pm art clear-app-profiles 

Uwaga: w przeciwieństwie do polecenia w Androidzie 13 lub starszym to polecenie nie czyści zewnętrznych danych profilu (`.dm`), które są instalowane z aplikacją.

Aby wyczyścić lokalne dane profilu i usunąć skompilowany kod wygenerowany na podstawie lokalnych danych profilu (czyli przywrócić stan instalacji), uruchom to polecenie:

adb shell pm compile --reset 

Uwaga: to polecenie nie usuwa skompilowanego kodu wygenerowanego na podstawie zewnętrznych danych profilu (`.dm`), które są instalowane z aplikacją.

Aby wyczyścić cały skompilowany kod, uruchom to polecenie:

adb shell cmd package compile -m verify -f 

Uwaga: to polecenie zachowuje lokalne dane profilu.