1. 程式人生 > >Android O 啟動優化的一些思路

Android O 啟動優化的一些思路

啟動優化其實是一個比較大的命題,在一些特地的場景下,快速啟動有比較強烈的需求,這篇部落格主要簡單的介紹一些在android O平臺上的進行啟動優化的思路與想法。

而優化啟動的一個很重要的東西就是如何來準確度量啟動時間,也就是說是否有比較好的辦法來度量整個系統的啟動耗時。畢竟只有能夠畢竟準確的度量了相應的時間,才能更好的瞭解分析每個啟動階段的情況。所以我打算按照如下的方式來組織:

  • Android 相關計時工具的介紹
  • 一些重點程式碼端的分析
  • 優化思路

Android 相關計時工具的介紹

1) bootchart工具 
在Android O當中,bootchart已經預設整合在Init當中。所以收集資料可以用以下步驟:

  • 只需要你通過開關開啟即可生效:“adb shell ‘touch /data/bootchart/enabled’”
  • 重啟裝置
  • $ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh抓取資料生成一張png圖片,即可進行分析。
  1. ant編譯
  2. java -jar bootchart.jar ../bootchart/bootchart.tgz 生成分析結果圖片:

    這裡寫圖片描述

從這張啟動圖片裡,我們能夠看到: 
1. 總共的啟動時間是30s,這裡指的是從kernel開始啟動的時間開始計時,一直到Android 啟動結束. 
2. Init 程序一直到13s左右才是啟動其他程序,如ueventd。 
3. Zygote64/Zygote程序大約在22s左右啟動。 
4. 這樣計算下來Android fw的啟動時間大致為8s左右。

這樣看起來就比較清晰了,Init程序13秒才開始工作的原因是什麼?這個時間如果能縮短的話啟動時間會效果很顯著。 
通過dmesg資訊,可以看到: 
[32m[ 13.227842] [0m[33minit[0m: init second stage started! 
[32m[ 13.237508] [0m[33mselinux[0m: SELinux: Loaded file_contexts\x0a 
[32m[ 13.243342] [0m[33mselinux[0m: SELinux: Loaded property_contexts from /plat_property_contexts & /nonplat_property_contexts.\x0a 
[32m[ 13.254522] [0m[33minit[0m: Running restorecon… 
[32m[ 13.593214] [0m[33mselinux[0m[31m: SELinux: Could not stat /dev/block: No such file or directory.\x0a[0m 
[32m[ 13.601607] [0m[33minit[0m[31m: waitpid failed: No child processes[0m 
[32m[ 13.606477] [0m[33minit[0m: Couldn’t load properties from /system/etc/prop.default: No such file or directory 
[32m[ 13.615416] [0m[33minit[0m: Couldn’t load properties from /prop.default: No such file or directory 
[32m[ 13.623768] [0m[33minit[0m: Couldn’t load properties from /odm/default.prop: No such file or directory 
[32m[ 13.631946] [0m[33minit[0m: Couldn’t load properties from /vendor/default.prop: No such file or directory 
[32m[ 13.641126] [0m[33minit[0m: Created socket ‘/dev/socket/property_service’, mode 666, user 0, group 0 
[32m[ 13.648925] [0m[33minit[0m: Parsing file /init.rc… 
[32m[ 13.653220] [0m[33minit[0m: Added ‘/init.environ.rc’ to import list 
[32m[ 13.658291] [0m[33minit[0m: Added ‘/init.usb.rc’ to import list 
[32m[ 13.663329] [0m[33minit[0m: Added ‘/init.angler.rc’ to import list 
[32m[ 13.668660] [0m[33minit[0m: Added ‘/vendor/etc/init/hw/init.angler.rc’ to import list 
[32m[ 13.675611] [0m[33minit[0m: Added ‘/init.usb.configfs.rc’ to import list 
[32m[ 13.681379] [0m[33minit[0m: Added ‘/init.zygote64_32.rc’ to import list 
[32m[ 13.688215] [0m[33minit[0m: Parsing file /init.environ.rc… 
[32m[ 13.692099] [0m[33minit[0m: Parsing file /init.usb.rc… 
[32m[ 13.696775] [0m[33minit[0m: Parsing file /init.angler.rc… 
[32m[ 13.701323] [0m[33minit[0m: Added ‘init.angler.usb.rc’ to import list 
[32m[ 13.706678] [0m[33minit[0m: Added ‘init.angler.diag.rc’ to import list 
[32m[ 13.712305] [0m[33minit[0m: Added ‘init.angler.sensorhub.rc’ to import list 
[32m[ 13.719668] [0m[33minit[0m: Parsing file init.angler.usb.rc… 
[32m[ 13.724264] [0m[33minit[0m: Parsing file init.angler.diag.rc…

確實是13s左右init程序才開始工作。所以第一步我們來想辦法把這個時間看看能不能縮短。

通過這個工具,我們能夠大致清楚了從系統啟動到Android啟動完成後的主要時間,同時也能夠簡單的分析出kernel啟動時間,zygote啟動時間,sysetmserver啟動時間,但是這個工具還是不能把Android 啟動階段畢竟清晰的展現出來,這個時候就需要使用到第二個工具了。

2) boot mesg

我們很高興的可以看到在Android中已經加入了一系列的mesg,我們可以通過這一系列的mesg可以抓出android fw啟動的相關時間。

這裡寫圖片描述

到此為止,我們大致能夠得出android 啟動的每個階段所耗費的時間了,後續我們來仔細分析每個階段的程式碼,看看都幹了啥。

第一步,關閉kernel log輸出:

  65 int console_printk[4] = {
  66         0,//DEFAULT_CONSOLE_LOGLEVEL,   /* console_loglevel */
  67         0,//DEFAULT_MESSAGE_LOGLEVEL,   /* default_message_loglevel */
  68         0,//MINIMUM_CONSOLE_LOGLEVEL,   /* minimum_console_loglevel */
  69         0,//DEFAULT_CONSOLE_LOGLEVEL,   /* default_console_loglevel */
  70 };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

簡單粗暴,全部關閉掉,重新編譯boot.img測試下,快了將近10s.。。。 
這裡寫圖片描述

通過檢視dmesg:

[32m[    5.276684][0m[33minit[0m: Parsing file /init.rc...
[32m[    5.276945][0m[33minit[0m: Added '/init.environ.rc' to import list
[32m[    5.276959][0m[33minit[0m: Added '/init.usb.rc' to import list
[32m[    5.276978][0m[33minit[0m: Added '/init.angler.rc' to import list
[32m[    5.276997][0m[33minit[0m: Added '/vendor/etc/init/hw/init.angler.rc' to import list
[32m[    5.277010][0m[33minit[0m: Added '/init.usb.configfs.rc' to import list
[32m[    5.277026][0m[33minit[0m: Added '/init.zygote64_32.rc' to import list
[32m[    5.278233][0m[33minit[0m: Parsing file /init.environ.rc...
[32m[    5.278331][0m[33minit[0m: Parsing file /init.usb.rc...
[32m[    5.278675][0m[33minit[0m: Parsing file /init.angler.rc...
[32m[    5.278851][0m[33minit[0m: Added 'init.angler.usb.rc' to import list
[32m[    5.278865][0m[33minit[0m: Added 'init.angler.diag.rc' to import list
[32m[    5.278878][0m[33minit[0m: Added 'init.angler.sensorhub.rc' to import list
[32m[    5.280094][0m[33minit[0m: Parsing file init.angler.usb.rc...
[32m[    5.280726][0m[33minit[0m: Parsing file init.angler.diag.rc...
[32m[    5.280817][0m[33minit[0m: Parsing file init.angler.sensorhub.rc...
[32m[    5.280908][0m[33minit[0m: Parsing file /vendor/etc/init/hw/init.angler.rc...
[32m[    5.280934][0m[33minit[0m[31m: could not import file '/vendor/etc/init/hw/init.angler.rc' from '/init.rc': No such file or directory[0m
[32m[    5.280951][0m[33minit[0m: Parsing file /init.usb.configfs.rc...
[32m[    5.281447][0m[33minit[0m: Parsing file /init.zygote64_32.rc...
[32m[    5.281581][0m[33minit[0m: Parsing file /system/etc/init...
[32m[    5.281607][0m[33minit[0m: Parsing file /vendor/etc/init...
[32m[    5.281632][0m[33minit[0m: Parsing file /odm/etc/init...
[32m[    5.281702][0m[33minit[0m: processing action (early-init)
[32m[    5.282227][0m[33minit[0m: starting service 'ueventd'...
[32m[    5.282722][0m[33minit[0m[31m: failed to open /acct/uid_0/pid_330/cgroup.procs: No such file or directory[0m
[32m[    5.282756][0m[33minit[0m[31m: createProcessGroup(0, 330) failed for service 'ueventd': No such file or directory[0m
[32m[    5.282980][0m[33minit[0m: processing action (wait_for_coldboot_done)
[32m[    5.283890][0m[31mmsm_rng:Data not available![0m
[32m[    5.284876][0m[33mueventd[0m: ueventd started!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

發現Init程序確實提前到kernel啟動5s左右。。