1. 程式人生 > >Android開機速度優化簡單回顧

Android開機速度優化簡單回顧

Android的開機速度,基本上沒人說快的,通常移植完系統後,馬上要看的事情就是優化開機時間,以下是簡單回憶以下以前做優化的那些事。

開機時間都花在哪?

優化開機時間,通常做的首先是那有有沒有BUG,明顯不合理的先解決,由於開發階段穩定性問題,一些地方可能延時加的大,或者頻率設的低,先記下來,後面定期還會再看。這些先不看的話,一般拿到機器,我們統計開機時間,主要看如下幾個時間段分佈:

  1. 開機按鍵時間、亮屏時間(基本固定,除非弄錯了,基本檢查一遍確定)
  2. uboot啟動時間
  3. 核心啟動後到bootanim退出時間

這裡我們主要關注的是第三個,也是優化的重點。這部分時間,具體都在幹啥,瓶頸是哪,可以通過bootchart很清楚的看到。以下結合以前抓的圖,簡要說一下(圖是很久之前抓的,比較懶,沒有再跑一遍過程)


上圖中bootanim的退出時間沒有截出來,實際圖是有的,大約是33s的時候結束。

這裡分析時,我們是分了幾個時間段:

  1. 核心開始啟動,到init程序開始執行。這個可以通過log看到。
  2. init程序執行,主要是處理init.rc中的命令,到core和mainl類服務開始啟動的時間,上圖中可以看到,服務大體都在一個時間點起來的,約7.5S時,這之前的一大段空窗期,也是要重點看的
  3. zygote啟動時間
  4. systemserver中各個服務啟動時間
  5. 應用啟動(systemui/launcher/keyguard..)

以上,具體分析看每段時間:

第一點另外處理,具體分析列印看是否有異常,這個值一般是很小的,不合理要和BSP同事一起查一下原因。

第二個主要是init.rc執行各種命令,這個可以通過在execute_one_command函式中統計測量 ,比如大於100ms的命令打印出來,再分析定位原因,這裡命令執行時間長基本算BUG,要和BSP工程師一起解決。

第三點主要zygote啟動問題,主要慢的原因,是載入資源和類庫,這個要讀nand,一般卡的時間比較長,圖中可以看到,zygote程序一溜的小粉紅,說明IO較多。這個preload過程消耗的時間,在logcat的log中,也會列印的,一般來說,都是在近10S左右。

第四個,zygote初始化完後,會fork system_server。 system_server程序啟動,耗時也是較長的。根據以前統計分析的結果,這裡的服務啟動,基本上都是花在packageManagerService的PackageScan中,這又是一個讀檔案,卡在檔案讀取中,時間長短,和預製app及安裝的app數量有關

第五個時間,是基本都準備ready後,啟動launcher等應用了,啟動完成後,systemServer請求SurfaceFlinger殺了bootanimation,就啟動完成了。


以上時間中,主要要優化的,還是第三步和第四步的IO慢問題,其他可優化的不多。比如CPU,常開四核performance模式啟動,也並沒提升多少,一般我們就不管了這個了。

咋優化?

確定優化方向後主要看怎麼優化這兩段耗時的地方:

1. Zygote的preload 資源和class

2. PackageManagerService的包掃描

這裡的第一個,最早之前有人直接是去掉preload或刪減,雖然可以加快一點開機速度,但是撿了芝麻丟了西瓜,根本不能這樣幹~

我們最早做的實現方式,是將preload做並行處理,畢竟現在都是多核處理器了,而且是preload是載入後還要解析處理的,並行會有一定幅度提升。

對於包掃描,這個不好拆成並行任務,不像preload那麼簡單幹淨。考慮過將PackageManager的資訊序列化後存起來,下次開機就不掃了,不過看起來改動有點大,不太好搞,也放棄了。

最後我們的實現的方式,就是linux上用的較多的readahead機制。具體實現細節就不展開說了,原理就是:

1. 統計開機過程中,讀取的塊資料資訊,記錄下來儲存

2.再次開機,通過記錄下來的塊資料讀取資訊,直接起一個服務,預先開始讀,zygote或packagemanagerservice要讀檔案的時候,檔案資料已經在cache中了。

實際用下來,這一招特別好,優化非常明顯。以下是實現了一個readahead後的bootchart圖:

可以看到:

1. zygote和system_server都提速了

2. zygote和system_server的IO時間,都降低非常大

3. 主要IO時間,跑到readahead程序中去了。

不過,以上實現,還是有可優化的地方:

1. readahead程序可以再提前,在system分割槽掛載後立刻啟動,這樣zygote中的IO應該可以再減小

2. 對system_server的IO,此時readahead已經結束了,按理不應該有了,這裡還是有IO,這一般是後裝apk導致,這個可以把readahead做的更健壯一些,不要只學習開始的一兩次。


其他NB的優化

另外還有一個很NB的技術,就是STD。這個我們也搞過,花費了大量的人力物力。STD開機時間,不算上uboot時間的話,基本都是在10S內,5~8S之間。不過這麼NB的技術,目前基本上也是廢棄了,用起來問題也挺多的:

1. 開機時間少了,關機時間拉長。

    由於是STD(Suspend to Disk),關機時需要將記憶體資料寫入nand,這塊也是挺麻煩的事情


2. 穩定性

    本身STD弄起來就比較複雜,BUG挺多的,另外使用STD,就相當於永不關機了,這也太考驗系統軟體的穩定性了...


3. 沒毛用

   一開始還能忽悠客戶,不過後來也沒人怎麼關心這個feature了,平白給自己找活幹,大家都不樂意使能它了