Android 开机速度优化-----ART 预先优化
轉載地址:http://blog.csdn.net/u010164190/article/details/51463492
Android開機速度
我們知道在L及以后的版本中,當系統升級后,或者恢復出廠設置后,或者第一次開機,其啟動時間往往很長,短的有3-4分鐘,而長的多達10分鐘,那么是原因導致的,我們將分析其原因.
ART 的前世今生
我們知道,在Android的最初的幾個版本,Android的app 運行在Dalvik中,完全是解釋性執行.在Android2.2中,Google把JVM中常用的技術JIT帶進了Dalvik,并且增加了多線程的處理能力.隨著歲月的流失,科技的進步,屌絲用戶期望的提高,手機廠商拼分數,拼情懷,拼硬件,跟蹤趙氏族人的style.終于Android 手機的HW,從singlecore 到了8cores,10 cores. RAM 也從256M,512M, 1G, 2G, 3G 到6G.內部存儲也從256M到了128G,256G.Google也順應潮流,終于在L 中,正式推出ART.
下面是ART 的架構圖.
首先ART兼容Dalvik.也就是說ART 能運行”dex”(Dalvik執行文件).因此對Androidapp的開發者來說,他們沒有什么區別.兩者最大的區別是:ART把JIT(Just-in-Time)變成了AOT(Ahead-of-Time).JIT需要在每次運行app時都需要執行一遍,而AOT 只需要執行一次,而后續再運行此app是不需要再執行,其明顯提高了性能.當然ART 這樣做,也是有代價的,那就是以空間換時間.ART能對應用的所有code做優化,其把bitcode 編譯為ELF文件.而ELF文件也往往比odex文件大很多.而JIT 只能對local/method做優化.ART的另一個缺點是其第一次執行優化時需要更長的時間.這也是導致第一次開機時間過長的原因.
此外在ART中,對GC 也有了很大的提高.我們知道在Dalvik中,GC首先需要”stopall the world”.然后再執行GC.其后果就是影響app的性能.其表現為Janks或者啟動時間長,卡頓等.相比較Dalvik的GC,ART 做了如下的提高:
在ART 中有幾種不同的GC 類型,分別是MS (Mark-Sweep),CMS(Concurrent Mark-Sweep),SS(Semi-space GC), GSS(Generational Semi-space ), MC(Mark Compact ),其default 是CMS.在ART 中,有三種GC plan,分別是Sticky GC: 只free 從上次GC 以來新分配的object,這種GC plan 是最常用的,也是最經濟的; Partial GC:只free 除zyogte外分配的空間;Full GC,釋放APP所有分配的Java空間.其執行時間為sticky GC < partial GC < full GC.ART 會根據heap的memory使用情況,選擇GC plan.在ART的GC 中,只有一次pause 在remark 階段.而Dalvik中有兩次pause, 一次是Root Mark階段, 另一次是remark 階段.如下圖所示.ART 對前臺應用和后臺應用采用不同的GC 算法來來達到性能和memory 的平衡.對于前臺應用采用CMS算法, CMS算法不會合并空間, 其好處是反應快,給用戶更好的performance體驗.但是其可能會導致heap的碎片較多.而對應后臺引用采用SS, GSS 和MC 算法, 這些算法可以合并壓縮memory空間, 有效的減少heap的碎片并節省memory.預先優化
對于ART我們現在有了如下認知,
ART 用AOT(ahead-of-time)進行優化.即在install app的時候,把dex 文件編譯為native code 并生成OAT file(依然是odex,但其格式是ELF).和Dalvik相比,其Performance有了較大的提升并且更節省功耗.在ART 中,沒有code cache(Dalvik 有JIT cache).OAT 文件直接map到memory里.ART 在zygote 啟動的時候, 會把初始化的class, object (boot.art) map 到memory 中去(大概10M 左右).在內存緊張的時候, 系統可以把一些proloaded classes swap out. 這樣不但加快了zygote的啟動速度,又提升了系統性能.ART 用dex2oat 工具來進行Dex 文件的本地編譯.其編譯時間比dexopt要長.OAT 文件比dexopt 生成的odex 文件要大.歸納起來就是ART 比Dilvik 性能更好,其把dex文件優化為為本地代碼,但是其體積大,編譯時間長,運行時的性能好.
由于dex優化為OAT文件的時間比較長,所以第一次開機時間(包括恢復工廠設置/OTA升級后)可能就會比較長如果我們沒有預先優化dex文件.所以我們可以用預先優化來規避這個問題, 但是其副作用就是其System image 比較大.在很多屌絲機上, 其內部存儲比較小, 這就需要一個平衡.要么忍受第一次的痛苦 (開機時間長), 要么加大投入增大內部存儲.
下面我們來看看相關的預先優化選項對ART優化后的OAT文件的大小和系統性能的影響.
· WITH_DEXPREOPT
我們可以在BoardConfig.mk里定義
WITH_DEXPREOPT := true
這樣整個system image 就會被預先優化. 由于在啟動時不再需要進行app的dex文件進行優化(dex2oat操作)從而提升其啟動速度.
· DONT_DEXPREOPT_PREBUILTS
如果我們不想把prebuilts目錄中的第三方應用進行預先優化(這些應用在他們的Android.mk文件中有include$(BUILD_PREBUILT) ).而是希望這些app通過playstore 或者app提供商進行升級.我們需要在BoardConfig.mk里進行如下的定義.
WITH_DEXPREOPT :=true
DONT_DEXPREOPT_PREBUILTS := true
· WITH_DEXPREOPT_BOOT_IMG_ONLY
這個選項只是把boot image 進行預先優化.簡單來說,其主要生成boot.art 和boot.oat.這能顯著的減少systemimage 大小.但是,所有的app 都需要在第一次啟動的時候進行優化需要花更長的boottime 時間.
我們需要在BoardConfig.mk里進行如下的定義
WITH_DEXPREOPT :=true
WITH_DEXPREOPT_BOOT_IMG_ONLY := true
· LOCAL_DEX_PREOPT
我們也可以控制單個APP是否需要預先優化.如果我們的APP是通過Google play 來進行升級的,或者為了平衡空間問題,我們可以在app的Android.mk 中設置如下屬性.
LOCAL_DEX_PREOPT :=false // 不進行預先優化LOCAL_DEX_PREOPT :=true // 進行預先優化· WITH_DEXPREOPT_PIC
我們知道ART 在system 有一份OAT file ,在運行時也會copy 一份到/data/ dalvik-cache下.如果我們內部存儲不夠,可以enable這個選項.但是這個選項可能會影響運行時的性能.因為ART 會disable和position相關的優化.
在device.mk 中添加,
WITH_DEXPREOPT :=true
WITH_DEXPREOPT_PIC :=true
· WITH_ART_SMALL_MODE
如果手機沒有足夠的空間,我們可以enable 這個宏.ART只會預先優化boot class.第一次啟動的時間會大大的提升,但是也會大大影響運行時性能.因為其它的appcode 是解釋性執行的.
在device.mk中添加,
WITH_ART_SMALL_MODE :=true
在Android 后面的版本中也許會修改成 device.mk:
PRODUCT_PROPERTY_OVERRIDES +=\
dalvik.vm.dex2oat-filter=interpret-only \
dalvik.vm.image-dex2oat-filter=speed
其它
· Preloaded Classes List
所謂preloaded classes list就是zygote在啟動是需要初始化的哪些類.這將會使所有的APPshare zygote啟動時初始化的類.從而APP 不需單獨去初始化這些類,進而提高了效率.proloaded classes 在frameworks/base/preloaded-classes中定義. 如果我們有自己SDK并且這些類是很多應用都會用到的,我們可以把這些常用的類添加到這個list中.注意如果添加過多無用的類會浪費memory,而沒有把APP都會用到的基礎類添加進來,也會讓每一個app都有一份基礎類copy,同樣浪費空間.
··Image Classes List
Image classes 是dex2oat初始化時的預先優化的類保存在boot.art文件中. 這個文件在系統啟動時map到memory 中去,這部分memory在memory緊張的情況下可以被swapout. Zygote啟動時,可以直接從memory中load這部分image.在 L 中,這部分classes list 和preloaded classes list 相同. 在M 中,可以定制需要添加哪些classess.方法如下,
在device.mk中添加,
PRODUCT_DEX_PREOPT_BOOT_FLAGS += –image-classes=
· ·Compiled Classes List
在L的后續版本,如M 中,可以用compiledclasses list 來預先優化boot classpath 中的某些classes.這對哪些內部存儲有限的手機非常有用.dex2oat在做優化時,首先會去check所優化的類是否在$OUT/system/etc/compiled-classeslist 中,如果沒有在這個列表中的classes則不會進行優化.只能解釋性執行,這樣雖然可以節省空間,但是勢必影響運行時的性能.
device.mk
PRODUCT_COPY_FILES += :system/etc/compiled-classes
所以如果我們想我們的第一次開機時間比較快,那么請用預先優化吧,在BoardConfig.mk里添加下面這行就可.
WITH_DEXPREOPT := true
總結
以上是生活随笔為你收集整理的Android 开机速度优化-----ART 预先优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ThinkPHP源码解读1
- 下一篇: 金山WPS面试