android ART編譯預優化

編譯預優化
DEX文件編譯比較花費時間。這在OTA或者工廠首次燒入程序後非常明顯。

可以在BoardConfig.mk文件中使能編譯預優化,在編譯時將會爲APK/jar做Dex優化(dex2oat):

WITH_DEXPREOPT := true  

如果完全的編譯預優化,則system.img的大小將會增加500MB。由於ASLR特性,預優化的DEX文件將被轉化並拷貝到data分區,所以data分區同樣增加500MB。
對於android 5.1,可以使用WITH_DEXPREOPT_PIC來禁止data分區中的優化文件,只在system分區存在編譯預優化的文件,這會對運行時稍微有些影響,這可以通過在BoardConfig.mk中添加編譯選項實現:

WITH_DEXPREOPT := true  
WITH_DEXPREOPT_PIC := true  

如果分區大小受限,則可以使用WITH_ART_SMALL_MODE參數減小編譯預優化後的文件大小,這同樣是在BoardConfig.mk文件中實現:

WITH_DEXPREOPT := true  
WITH_ART_SMALL_MODE := true  

WITH_ART_SMALL_MODE主要是將BootClasspath和大多數APKs用到的Jar文件做dex2oat轉化,只做傳統的解釋優化。而不會爲apk啓動編譯預先優化,這將加速首次系統啓動,但也影響app運行時性能。但是影響是有限的,這一優化將增加200MB的系統分區大小。

在往後的版本中,該優化選項去掉了。使用如下:

+WITH_DEXPREOPT := true  
+PRODUCT_PROPERTY_OVERRIDES +=\  
+               dalvik.vm.dex2oat-filter=interpret-only \  
+               dalvik.vm.image-dex2oat-filter=speed  

編譯預優化可能的問題
一類問題是64bit處理器上遇到的ABI的適用性問題。

共享UID問題

在64bit機器上共享UID非常複雜:

在64bit機器上,32bit和64bit app都能運行,有兩種Zygote進程:“Zygote”和“Zygote64”。“Zygote”用於fork 32bit應用進程,“Zygote64”用於fork 64bit進程。
如果應用共享UID(在AndroidManifest.xml文件中使用android.shareUserId),尤其是當它們共享進程時(使用“android:process”指定app運行的目標進程),則所有的共享UID相同的進程必須運行在相同的進程中。
只有不依賴JNI的apk,可以被同時編譯成32bit和64bit。如果使能了編譯預優化,在編譯時將生成二進制文件。對於64bit機器,絕大多少apk默認將被編譯成64bit二進制,在編譯預優化完成後,爲了節省空間apk的classes.dex將被刪除,但是如果apk依賴native代碼,並且native代碼被編譯成了32bit二進制,apk同樣要被編譯成32bit二進制。
問題來了,如果一個32bit apk和一個64bit apk使用共享UID,這將導致未知問題。
如果apk不共享UID,將不會出現問題。
有三種解決方法:

對於所有共享相同UID的apk, 在編譯的.mk文件中添加LOCAL_MULTILIB := both以支持兩個版本的odex。

在.mk文件中使用LOCAL_DEX_PREOPT := nostripping以確保classes.dex文件不被刪除,這將節約存儲空間,但是影響啓動時間。
創建僞link以使PackageManager運行在32bit模式,這通過將ystem/app/(appname)/lib/arm/通過符號鏈接到任意的32bit庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章