都9102年了,Android 冷啓動優化仍是隻會老三樣嗎

圖:Benjamin Suter

性能優化一直都是一個 Android 開發者逃不過的話題,啓動優化則更是重中之重。啓動速度能夠直接影響一個 App 的留存率和轉化率,沒有人會但願本身點擊以後還要等一會纔打開。html

可是當我一番調研後發現,網上大部分啓動優化相關的文章,套路都差很少,我稱之爲老三樣。python

什麼是老三樣?linux

  1. 將啓動頁主題背景設置成閃屏頁圖片

這麼作的目的主要是爲了消除啓動時的黑白屏,給用戶一種秒響應的感受,可是並不會真正減小用戶啓動時間,僅屬於視覺優化。android

  1. 主頁面佈局優化

1)經過減小冗餘或者嵌套佈局來下降視圖層次結構 2)用 ViewStub 替代在啓動過程當中不須要顯示的 UI 控件git

  1. Application 和 主 Activity 的 onCreate 中異步初始化某些代碼

由於在主線程上進行資源初始化會下降啓動速度,因此能夠將沒必要要的資源初始化延遲,達到優化的效果。可是這裏要注意懶加載集中化的問題,別用戶啓動時間快了,可是沒法在界面上操做就尷尬了。github

老三樣並不說是無論用或者過期了,只是這三種優化方式都是很是基礎的方式,當你的啓動優化遇到了瓶頸,是不可以再經過這三種方式突破的。chrome

並且只會基礎的優化方式,並不會在履歷中展示出優點。shell

因此今天說說在老三樣的基礎優化之上還有哪些可行的方案。json


進階方案一 經過 systrace 查找耗時代碼

具體步驟xcode

1)清空手機後臺

2)在命令行執行

python $ANDROID_HOME/platform-tools/systrace/systrace.py gfx view wm am pm ss dalvik app sched -b 90960 -a 你的包名  -o test.log.html
複製代碼

這一步須要你係統環境配置了 ANDROID_HOME 環境變量。

3)運行你的App,正常操做到你想測性能的地方,而後再命令行窗口中按 Enter 鍵中止收集

4)用 chrome(只支持此瀏覽器)打開生成的 test.log.html 結果文件,打開效果以下圖:


目前須要關心地方就是咱們的應用進程相關的,也就是紅框圈起來的地方。

圖中的 F 表明繪製幀,黃色/紅色表示該幀繪製超時,綠色表明繪製正常,也就是在16.6ms內繪製完一幀。

關於 systrace 如何使用能夠參考這篇文章 性能工具Systrace

放大能夠看到在啓動過程當中,控件渲染耗時狀況


因此能夠很容易發現哪些啓動過程當中沒有用到的 UI 控件也被渲染了,這時就能夠用 ViewStub 去替代。

可是如今能夠看到的都是系統調用的耗時狀況,由於谷歌預先在代碼裏關鍵的地方加上了監控,若是想要看到本身方法的耗時,

那須要手動在方法入口加上 Trace.beginSection("TAG")

在方法結束的地方加上Trace.endSection()

這樣就能夠在生成的結果中看到咱們自定義的 tag。

若是不少地方你都想加上監控,手動加是確定不合適的,這裏推薦函數插樁方式自動加上監控代碼,參考 systrace+函數插樁

這種方式不只能夠幫助監控啓動過程當中性能問題,再作卡頓優化的時候也能夠用這種方式。

定位到了耗時方法,再作一些針對性的優化就相對容易了。


進階方案二 經過 redex 重排列 class 文件

redex 是 Facebook 開源的一款字節碼優化工具,目前只支持 mac 和 linux。

咱們用的是裏面的 interdex 功能來重排列咱們 dex 中的 class 文件,那麼爲何重排列 class 文件能夠優化啓動速度?

簡單的說,經過文件重排列的目的,就是將啓動階段須要用到的文件在 APK 文件中排布在一塊兒,儘量的利用 Linux 文件系統的 pagecache 機制,用最少的磁盤 IO 次數,讀取儘量多的啓動階段須要的文件,減小 IO 開銷,從而達到提高啓動性能的目的

具體能夠參考支付寶的這篇 《經過安裝包重排布優化 Android 端啓動性能》

因此咱們着手要作的就三件事:

1)安裝配置 redex 2)得到啓動過程當中 class 文件的加載順序 3)根據這個順序重排列 dex 中的 class 文件

具體步驟

1)下載 redex,配置環境(Mac OS)

git clone https://github.com/facebook/redex.git

xcode-select --install

brew install autoconf automake libtool python3

brew install boost jsoncpp
複製代碼

2)編譯安裝 redex

cd redex

autoreconf -ivf && ./configure && make

sudo make install
複製代碼

編譯時間較久,不想幹等着,能夠加上 say 指令,編譯完成後語音通知

autoreconf -ivf && ./configure && make && say '編譯完成'

3)配置優化項

由於 redex 默認不開啓 interdex,因此咱們要在配置文件中加上相應的配置,在 redex 文檔中有說明

因此咱們打開配置文件

cd redex/config/
vi default.config
複製代碼

按照下圖配置


4)得到啓動 class 加載順序列表

這裏按照 redex 提供的工具獲取,可是須要手機有 root 權限

首先清空後臺進程,而後打開你的應用

獲取你的應用的 pid

adb shell ps | grep 你的應用包名
複製代碼

收集堆內存,須要 root 權限

adb root
adb shell am dumpheap YOUR_PID /data/local/tmp/SOMEDUMP.hprof
複製代碼

把堆內存文件拉取到電腦的某個位置

adb pull /data/local/tmp/SOMEDUMP.hprof YOUR_DIR_HERE/.
複製代碼

經過 python 腳本解析堆內存,生成類加載順序列表

python redex/tools/hprof/dump_classes_from_hprof.py --hprof YOUR_DIR_HERE/SOMEDUMP.hprof > list_of_classes.txt
複製代碼

ps: 這個腳本支持 Python 2,執行過程當中若是遇到某個庫沒安裝之類的,直接經過 pip install 缺失的庫 就能夠

5)經過 redex 處理

ANDROID_SDK=你的Android sdk路徑 redex input.apk -o output.apk
複製代碼

6)從新簽名

這時候生成的 output.apk 是不能直接安裝的,須要從新簽名,我測試用的是 debug 包,因此從新簽了debug 的簽名

jarsigner -keystore ~/.android/debug.keystore -storepass android -keypass android output.apk androiddebugkey
複製代碼

到這就能夠從新安裝測試了,按照 facebook 的說法和一些大廠的實踐,啓動速度大概能夠提升 10%~20%,在低端機型上效果應該更明顯。

關於 redex 的使用和相關配置文檔,均可以在 redex/docs/ 目錄下查看。

其餘相關

啓動耗時測量

爲了正確診斷冷啓動的性能,須要冷啓動的時間指標,下面有兩種簡單的方式:

adb命令adb shell am start -S -W 包名/啓動類的全名

例如:

adb shell am start -S -W com.android.helloword/com.android.helloword.MainActivity
複製代碼


  • ThisTime : 最後一個 Activity 的啓動耗時(例如從 LaunchActivity - >MainActivity「adb命令輸入的Activity」 , 只統計 MainActivity 的啓動耗時)
  • TotalTime : 啓動一連串的 Activity 總耗時.(有幾個Activity 就統計幾個)
  • WaitTime : 應用進程的建立過程 + TotalTime

這裏咱們關注 TotalTime 就能夠。

谷歌在 Android4.4(API 19)上也提供了測量方法,在 logcat 中過濾 Displayed 字段


輸出的值表示在啓動過程和完成在屏幕上繪製相應 Activity 之間通過的時間,其實和上面的方式獲得的結果是同樣的。

關於 Android App 的冷啓動過程和一些概念能夠參考谷歌官方文檔 「App startup time 」

因爲一些緣由,還有一些優化方法沒有實踐,有興趣的能夠自行了解:

1)啓動過程當中的 GC 優化,儘可能減小 GC 次數,避免大量或者頻繁建立對象,如必須,可嘗試放到 Native 實現

2)線程優化,儘量減小 cpu 調度,具體就是控制線程數量和調度

3)在類加載的過程當中經過 Hook 去掉類驗證的過程,能夠在 systrace 生成的文件中看到 verifyClass 過程,由於須要校驗方法的每個指令,因此是一個比較耗時的操做

以上就是我關於 Android 冷啓動優化的一些總結,水平有限,不免出現不許確的地方,歡迎指正​。​

本文首發於公衆號「後知後jue」,微信搜索關注回覆「1024」,你懂的!

相關文章
相關標籤/搜索