Android开机速度优化简单回顾
Android的開機速度,基本上沒人說快的,通常移植完系統后,馬上要看的事情就是優化開機時間,以下是簡單回憶以下以前做優化的那些事。
開機時間都花在哪?
優化開機時間,通常做的首先是那有有沒有BUG,明顯不合理的先解決,由于開發階段穩定性問題,一些地方可能延時加的大,或者頻率設的低,先記下來,后面定期還會再看。這些先不看的話,一般拿到機器,我們統計開機時間,主要看如下幾個時間段分布:
內核優化
可以通過添加打印module init的log,來check每個module初始化時的時間。從而找到花費時間比較多的module:
--- a/init/main.c +++ b/init/main.c @@ -785,7 +785,7 @@ int __init_or_module do_one_initcall(initcall_t fn)if (initcall_blacklisted(fn))return -EPERM;- if (initcall_debug) + if (1)ret = do_one_initcall_debug(fn);優化方案:
這里我們主要關注的是第三個,也是優化的重點。這部分時間,具體都在干啥,瓶頸是哪,可以通過bootchart很清楚的看到。以下結合以前抓的圖,簡要說一下(圖是很久之前抓的,比較懶,沒有再跑一遍過程)
上圖中bootanim的退出時間沒有截出來,實際圖是有的,大約是33s的時候結束。
這里分析時,我們是分了幾個時間段:
以上,具體分析看每段時間:
第一點另外處理,具體分析打印看是否有異常,這個值一般是很小的,不合理要和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了,平白給自己找活干,大家都不樂意使能它了
轉至:Android開機速度優化簡單回顧_freshui的專欄-CSDN博客_android 開機優化
打開 bootchart 收集開機數據
1. adb shell 'touch /data/bootchart/enabled'首先使能 bootchart,bootchart 操作的前提是存在 enable 標記,所以在你不需要收集數據的時候別忘了刪除這個標記。2. - sudo apt-get install pybootchartgui- $ANDROID_BUILD_TOP/system/core/init/grab-bootchart.shgrab-bootchart.sh 腳本是 Google 封裝的一系列操作的合集跟使用下面手動操作的結果是一樣的。* 手動操作1. (可選) echo $TIME_OUT > /data/bootchart/start添加 bootchart timeout 時間2. reboot 重啟3. 可以看到 bootchart 生成的數據文件和 log 都被保存在 /data/bootchart 路徑下4. tar -zcf boochart.tgz *5. 使用 adb pull 命令將文件拷貝出來Bug解決辦法
設置了 enabled后,重啟,發現無法開機了,從內核log看一直在crash
經過一番百度,Google
有的Blog是說把 system/core/init/bootchart.cpp中的
stat.replace(open + 1, close - open - 1, full_name);刪除就好了
我試過,確實,可以開機了
但是又想了想,谷歌會沒發現這個問題么?不至于吧
真相只有一個!
然后對比了谷歌7.0 8.1 甚至 9.0 的源代碼,開啟了漫長2個小時的地毯上搜索....
最終在 Google 的提交記錄上找到相關修復提交
system/core/init/Android.mkLOCAL_SANITIZE := integer========》LOCAL_SANITIZE := signed-integer-overflow有梯子的可以直接看原生提交
https://android-review.googlesource.com/c/platform/system/core/+/445032/2/init/Android.mk#b97雖然不知道這是什么,但從字面意思大概猜到是和內存溢出有關系吧
LOCAL_SANITIZE
然后再百度搜索一波 LOCAL_SANITIZE signed-integer-overflow
是什么
官方解釋
Android 的構建系統還使用了 UBSan 的整數溢出檢查功能。UBSan 還支持 unsigned-integer-overflow,這不是嚴格意義上的未定義行為,但它包含在擦除器中。在生成文件中,可以將 LOCAL_SANITIZE 設置為 signed-integer-overflow、unsigned-integer-overflow 或 combination flag integer,啟用 signed-integer-overflow、unsigned-integer-overflow、integer-divide-by-zero、shift-base 和 shift-exponent,以啟用這些行為。在 blueprint 文件中,可以將 Misc_undefined 設置為所需的標志,啟用這些行為。這些 UBSan 目標,尤其是 unsigned-integer-overflow,廣泛用于 mediaserver 組件中,以用來消除任何潛在的整數溢出漏洞
在 Android 中,當出現未定義的行為時,默認的做法是中止程序。但是,從 2016 年 10 月開始,Android 中的 UBSan 將提供一個可選的運行時庫,其報告的錯誤信息將更加詳細,包括出現的未定義行為類型、文件和源代碼行信息
在 Android.mk 文件中,可通過以下方式啟用該庫:
LOCAL_SANITIZE:=unsigned-integer-overflow signed-integer-overflow LOCAL_SANITIZE_DIAG:=unsigned-integer-overflow signed-integer-overflow在 Linux PC 機上生成 bootchart 圖表
PC 機安裝 bootchart 工具
sudo apt-get install bootchart sudo apt-get install pybootchartgui生成 bootchar 圖表
拷貝 bootchart.tgz 到 PC 中,并執行下面的命令生成圖表
bootchart bootchart.tgz但很有可能會出現如下錯誤?
那么就要更新編譯一下自己的bootchartgui工具
由于Ubuntu版本的pybootchartgui不能解析busybox上的bootchart數據,所以這里出現了錯誤,需要用另外一個版本bootchart2的工具來處理。用git下載bootchart2后需要執行make后才能使用pybootchartgui:
git clone https://github.com/xrmx/bootchart.git下載完成之后,進到目錄里面執行make操作
然后執行如下命令即可
python ./bootchart/pybootchartgui.py bootlog.tar.gz至此bootchart.png文件生成成功
https://elinux.org/images/a/a1/Abs2011_bird_readahead.pdf
總結
以上是生活随笔為你收集整理的Android开机速度优化简单回顾的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android:completionth
- 下一篇: Android中使用字体文件