實作 ART 及時編譯器

Android 執行階段 (ART) 包含即時 (JIT) 編譯器,可透過程式碼剖析持續改善 Android 應用程式執行時的效能。JIT 編譯器可補足 ART 目前的預先 (AOT) 編譯器,並改善執行階段效能、節省儲存空間,以及加快應用程式和系統更新速度。這個程式庫也能改善 AOT 編譯器的效能,避免在自動更新應用程式期間,或避免在無線更新 (OTA) 期間重新編譯應用程式時,降低系統運作速度。

雖然 JIT 和 AOT 使用相同的編譯器,且採用類似的最佳化組合,但產生的程式碼可能不盡相同。JIT 會使用執行階段類型資訊,可進行更佳的內嵌作業,並可進行堆疊替換 (OSR) 編譯,所有這些都會產生略有不同的程式碼。

JIT 架構

JIT 架構
圖 1. JIT 架構。

JIT 編譯

JIT 編譯涉及下列活動:

個人資料導覽通訊
圖 2. 設定檔引導編譯。
  1. 使用者執行應用程式,然後觸發 ART 載入 .dex 檔案。
    • 如果 .oat 檔案 (.dex 檔案的 AOT 二進位檔) 可用,ART 會直接使用該檔案。雖然 .oat 檔案會定期產生,但不一定會包含編譯的程式碼 (AOT 二進位檔)。
    • 如果 .oat 檔案不含編譯程式碼,ART 會透過 JIT 和轉譯器執行 .dex 檔案。
  2. 任何未根據 speed 編譯篩選器編譯的應用程式,都會啟用 JIT (也就是「盡可能從應用程式編譯」)。
  3. JIT 設定檔資料會轉儲至系統目錄中的檔案,該檔案只有應用程式可存取。
  4. AOT 編譯 (dex2oat) 守護程式會剖析該檔案,以便驅動編譯作業。

    JIT Daemon
    圖 3. JIT 守護程式活動。

Google Play 服務是其他應用程式使用的例子,運作方式與共用程式庫類似。

JIT 工作流程

JIT 架構
圖 4. JIT 資料流。
  • 分析資訊會儲存在程式碼快取中,並在記憶體壓力下進行垃圾收集。
    • 應用程式在背景執行時拍攝的快照不一定會包含完整資料 (也就是 JITed 的所有內容)。
    • 系統不會嘗試確保所有內容都已記錄 (因為這可能會影響執行階段效能)。
  • 方法可處於三種狀態:
    • 解譯 (dex 程式碼)
    • JIT 編譯
    • AOT 編譯
    如果同時存在 JIT 和 AOT 程式碼 (例如因重複的去最佳化而產生),系統會優先採用 JIT 程式碼。
  • 如要在不影響前景應用程式效能的情況下執行 JIT,記憶體需求取決於相關應用程式。大型應用程式需要的記憶體比小型應用程式多。一般來說,大型應用程式會在 4 MB 左右穩定下來。

開啟 JIT 記錄功能

如要開啟 JIT 記錄功能,請執行下列指令:

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

停用 JIT

如要停用 JIT,請執行下列指令:

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

強制編譯

如要強制執行編譯,請執行下列指令:

adb shell cmd package compile

強制編譯特定套件的常見用途:

  • 以設定檔為依據:
    adb shell cmd package compile -m speed-profile -f my-package
    
  • 完整:
    adb shell cmd package compile -m speed -f my-package
    

強制編譯所有套件的常見用途:

  • 以設定檔為基礎:
    adb shell cmd package compile -m speed-profile -f -a
    
  • 完整:
    adb shell cmd package compile -m speed -f -a
    

清除設定檔資料

Android 13 以下版本

如要清除本機設定檔資料並移除已編譯的程式碼,請執行下列指令:

adb shell pm compile --reset 

在 Android 14 以上版本

如果只要清除本機設定檔資料,請按照以下步驟操作:

adb shell pm art clear-app-profiles 

注意:與 Android 13 以下版本的指令不同,這個指令不會清除透過應用程式安裝的外部設定檔資料 (".dm")。

如要清除本機設定檔資料,並移除由本機設定檔資料產生的編譯代碼 (也就是將其重設為安裝狀態),請執行下列指令:

adb shell pm compile --reset 

注意:這個指令不會移除隨應用程式一併安裝的外部設定檔資料 (`.dm`) 產生的已編譯程式碼。

如要清除所有已編譯的程式碼,請執行下列指令:

adb shell cmd package compile -m verify -f 

注意:這個指令會保留本機設定檔資料。