實施 ART 即時 (JIT) 編譯器

Android 運行時 (ART) 包括一個即時 (JIT) 編譯器,該編譯器具有代碼分析功能,可在 Android 應用程序運行時不斷提高它們的性能。 JIT 編譯器補充了 ART 當前的提前 (AOT) 編譯器,提高了運行時性能,節省了存儲空間,並加速了應用程序和系統更新。它還通過避免在自動應用程序更新期間系統減速或在無線 (OTA) 更新期間重新編譯應用程序來改進 AOT 編譯器。

儘管 JIT 和 AOT 使用具有相似優化集的相同編譯器,但生成的代碼可能並不相同。 JIT 利用運行時類型信息,可以進行更好的內聯,並使堆棧替換 (OSR) 編譯成為可能,所有這些都會生成略有不同的代碼。

即時架構

即時架構
圖 1. JIT 架構。

即時編譯

JIT 編譯涉及以下活動:

配置文件引導的comp
圖 2.配置文件引導的編譯。
  1. 用戶運行應用程序,然後觸發 ART 加載.dex文件。
    • 如果.oat文件( .dex文件的 AOT 二進製文件)可用,ART 會直接使用它。儘管.oat文件會定期生成,但它們並不總是包含已編譯的代碼(AOT 二進製文件)。
    • 如果.oat文件不包含編譯後的代碼,ART 會通過 JIT 和解釋器運行來執行.dex文件。
  2. 對於任何未根據speed編譯過濾器編譯的應用程序(即“盡可能從應用程序編譯”)啟用 JIT。
  3. JIT 配置文件數據被轉儲到系統目錄中只有應用程序可以訪問的文件中。
  4. AOT 編譯 ( dex2oat ) 守護程序解析該文件以驅動其編譯。

    JIT 守護進程
    圖 3. JIT 守護程序活動。

Google Play 服務是其他應用程序使用的示例,其行為類似於共享庫。

JIT 工作流程

即時架構
圖 4. JIT 數據流。
  • 分析信息存儲在代碼緩存中,並在內存壓力下進行垃圾回收。
    • 不能保證當應用程序在後台時拍攝的快照將包含完整的數據(即,所有被 JIT 處理的數據)。
    • 沒有嘗試確保記錄所有內容(因為這會影響運行時性能)。
  • 方法可以處於三種不同的狀態:
    • 解釋(dex 代碼)
    • 即時編譯
    • 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
    

清除配置文件數據

要清除配置文件數據並刪除已編譯的代碼,請運行以下命令:

  • 對於一個包:
    adb shell cmd package compile --reset my-package
    
  • 對於所有包:
    adb shell cmd package compile --reset -a