實施ART即時(JIT)編譯器

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守護程序
    圖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
    

清除個人資料數據

要清除概要文件數據並除去編譯的代碼,請運行以下命令:

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