實作 ART 及時編譯器

Android 執行階段 (ART) 包含即時 (JIT) 編譯器,可進行程式碼剖析,持續提升 Android 應用程式的執行效能。JIT 編譯器可輔助 ART 目前的預先 (AOT) 編譯器,提升執行階段效能、節省儲存空間,並加快應用程式和系統更新速度。此外,這項技術還能避免系統在自動更新應用程式或無線更新 (OTA) 期間重新編譯應用程式時變慢,進而提升 AOT 編譯器效能。

雖然 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 資料流程。
  • 剖析資訊會儲存在程式碼快取中,並在記憶體壓力下進行垃圾收集。
    • 我們無法保證應用程式在背景執行時擷取的快照會包含完整資料 (即所有 JIT 編譯的內容)。
    • 系統不會嘗試確保所有內容都已錄製 (因為這可能會影響執行階段效能)。
  • 方法可處於三種不同狀態:
    • 解譯 (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 

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