Wdrażanie kompilatora ART just-in-time (JIT)

Środowisko uruchomieniowe systemu Android (ART) zawiera kompilator just-in-time (JIT) z profilowaniem kodu, który stale poprawia wydajność aplikacji systemu Android podczas ich uruchamiania. Kompilator JIT uzupełnia obecny kompilator ART z wyprzedzeniem (AOT) i poprawia wydajność środowiska wykonawczego, oszczędza miejsce w pamięci oraz przyspiesza aktualizacje aplikacji i systemu. Ulepsza również kompilator AOT, unikając spowolnienia systemu podczas automatycznych aktualizacji aplikacji lub ponownej kompilacji aplikacji podczas aktualizacji bezprzewodowych (OTA).

Chociaż JIT i AOT używają tego samego kompilatora z podobnym zestawem optymalizacji, wygenerowany kod może nie być identyczny. JIT wykorzystuje informacje o typie środowiska uruchomieniowego, może wykonywać lepsze wstawianie i umożliwia kompilację wymiany stosu (OSR), z których każda generuje nieco inny kod.

Architektura JIT

Architektura JIT
Rysunek 1. Architektura JIT.

Kompilacja JIT

Kompilacja JIT obejmuje następujące czynności:

Kompilacja oparta na profilach
Rysunek 2. Kompilacja sterowana profilem.
  1. Użytkownik uruchamia aplikację, która następnie uruchamia ART w celu załadowania pliku .dex .
    • Jeśli plik .oat (plik 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 (plik binarny AOT).
    • Jeśli plik .oat nie zawiera skompilowanego kodu, ART działa przez JIT i interpreter, aby wykonać plik .dex .
  2. JIT jest włączony dla każdej aplikacji, która nie jest skompilowana zgodnie z filtrem kompilacji speed (który mówi „kompiluj tyle, ile możesz z aplikacji”).
  3. Dane profilu JIT są zrzucane do pliku w katalogu systemowym, do którego ma dostęp tylko aplikacja.
  4. Demon kompilacji AOT ( dex2oat ) analizuje ten plik, aby sterować jego kompilacją.

    Demon JIT
    Rysunek 3. Działania demona JIT.

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

Przepływ pracy JIT

Architektura JIT
Rysunek 4. Przepływ danych JIT.
  • Informacje o profilowaniu są przechowywane w pamięci podręcznej kodu i poddawane wyrzucaniu śmieci pod presją pamięci.
    • Nie ma gwarancji, że migawka zrobiona, gdy aplikacja działała w tle, będzie zawierała kompletne dane (tj. wszystko, co zostało JITowane).
    • Nie ma próby upewnienia się, że wszystko jest rejestrowane (ponieważ może to wpłynąć na wydajność środowiska wykonawczego).
  • Metody mogą być w trzech różnych stanach:
    • interpretowane (kod dex)
    • Skompilowano JIT
    • Skompilowano AOT
    Jeśli istnieje zarówno kod JIT, jak i AOT (np. z powodu powtarzających się deoptymalizacji), preferowany jest kod JITed.
  • Wymaganie pamięci do uruchomienia JIT bez wpływu na wydajność aplikacji na pierwszym planie zależy od danej aplikacji. Duże aplikacje wymagają więcej pamięci niż małe aplikacje. Ogólnie rzecz biorąc, duże aplikacje stabilizują się w okolicach 4 MB.

Włączanie rejestrowania JIT

Aby włączyć rejestrowanie JIT, uruchom następujące 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 następujące polecenia:

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

Wymuszanie kompilacji

Aby wymusić kompilację, uruchom następujące polecenie:

adb shell cmd package compile

Typowe przypadki użycia do wymuszenia kompilacji określonego pakietu:

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

Typowe przypadki użycia dla wymuszenia kompilacji wszystkich pakietów:

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

Usuwanie danych profilu

Aby wyczyścić dane profilu i usunąć skompilowany kod, uruchom następujące polecenie:

  • Dla jednego pakietu:
    adb shell cmd package compile --reset my-package
    
  • Dla wszystkich pakietów:
    adb shell cmd package compile --reset -a