開機啓動慢的原因分析

        最近的項目開機啓動花了40多秒,正常開機只需要28秒就能開機起來。

內核的啓動我沒有去分析,另一個同事分析的。我主要是分析從SystemServer啓來到開機動畫結束顯示解鎖界面的這段時間,也就是開機動畫的第三個動畫開始到結束這段時間,這是個比較耗時階段,一般都在17秒左右(見過牛B的手機,只需5秒)。

        SystemServer分兩步執行:init1和init2。init1主要是初始化native的服務,代碼在system_init.cpp的system_init,初始化了SurfaceFlinger和SensorService這兩個native的服務。init2啓動的是java的服務,比如ActivityManagerService、WindowManagerService、PackageManagerService等,在這個過程中PackageManagerService用的時間最長,因爲PackageManagerService會去掃描特定目錄下的jar包和apk文件。

        在開機時間需要40多秒的時,從Log上可以看到,從SurfaceFlinger初始化到動畫結束,要27秒左右的時間,即從SurfaceFlinger::init的LOGI("SurfaceFlinger is starting")這句Log到void SurfaceFlinger::bootFinished()的LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ),需要27秒左右的時間,這顯然是太長了,但到底是慢在哪了呢?應該在箇中間的點,二分一下,於是想到了以啓動服務前後作爲分隔:是服務啓動慢了,還是在服務啓動後的這段時間慢?以ActivityManagerService的Slog.i(TAG, "System now ready")的這句Log爲分割點,對比了一下,在從SurfaceFlinger is starting到System now ready多了7秒左右的時間,這說明SystemServer在init1和init2過程中啓動慢了,通過排查,發現在init1啓動的時候,花了7秒多的時間,也就是system_init的LOGI("Entered system_init()")到LOGI("System server: starting Android runtime.\n")這段時間用了7秒多,而正常情況是400毫秒便可以初始化完,通過添加Log看到,在SensorService啓動時,用了比較長的時間。

        不斷的添加Log發現,在啓動SensorService時候,關閉設備文件變慢了,每次關閉一個/dev/input/下的設備文件需要100ms左右,而SensorService有60~70次的關閉文件,大概有7s左右的時間。
調用流程是:
frameworks/base/cmds/system_server/library/system_init.cpp:  system_init->SensorService::instantiate
frameworks/native/services/sensorservice/SensorService.cpp:  void SensorService::onFirstRef()->SensorDevice& dev(SensorDevice::getInstance())
hardware/libsensors/SensorDevice.cpp:    SensorDevice::SensorDevice()->sensors_open
hardware/libsensors/sensors.cpp:         open_sensors->sensors_poll_context_t
sensors_poll_context_t執行打開每個傳感器設備時,遍歷/dev/input/目錄下的設備文件,以匹配當前需要打開的設備,遍歷文件是在
hardware/libsensors/SensorBase.cpp的openInput下實現,如果打開的設備文件不是正在打開的設備文件,會執行下面語句的else部分:
   if (!strcmp(name, inputName)) {
       strcpy(input_name, filename);
       break;
   } else {
close(fd);
       fd = -1;
   }
close每次需要100ms左右,每次打開傳感器部分都執行去這樣的操作,導致了在這有大概7s左右的延遲。

優化完這段時間後,系統啓動變快了7秒,但還是慢,因爲對比可以發現:

開機28秒:

04-16 16:14:22.205   140   343 I SurfaceFlinger: Using composer version 1.0
04-16 16:14:34.167   527   542 I ActivityManager: System now ready
04-16 16:14:39.089   140   605 I SurfaceFlinger: Boot is finished (16985 ms)

開機34秒:

04-18 15:32:55.565 I/SurfaceFlinger(  242): SurfaceFlinger is starting
04-18 15:33:05.214 I/ActivityManager(  622): System now ready
04-18 15:33:17.658 I/SurfaceFlinger(  242): Boot is finished (22091 ms)

可見還是慢了6秒。但這6秒慢在了似乎是在服務啓動後的時間,這個時候比較難分析了,原因是這是所有的服務起來了,而且發出了bootcomplete廣播,應用也開始起來,但還沒用解鎖,開始以爲是Launcher起來慢了,但換了一個Google原始的Launcher進去,並沒有變快。

       我們用兩個版本的手機,W制式的跟TD的,過來幾天發現TD的手機比W的開機快,而且TD的28秒左右能起來,但W的卻要34秒,問了一下驅動的同事,W跟TD的並沒有什麼區別,所以除了Modem不一樣以外,其他的都一樣。找了一天,依然毫無結果。從Log中看,都只這慢一點,那慢一點,只有在Packmanager在掃描包的過程中,W+GSM需要6秒左右的時間,而TD+GSM只需要3秒左右的時間,但也不至於花費6秒的時間。但軟件版本是一樣的,猜測是硬件的問題,但硬件都是一樣的,除了Modem不一樣以外,開始懷疑Modem,W+GSM是正常的開機模式,而TD+GSM卻是在mbp模式下開機的,弄成一樣的開機模式,依然沒有改變兩個開機時間。到最才發現W的手機用的是16G的EMMC,而TD的手機用的是32G的EMMC,而且32G的EMMC比16G的EMMC讀寫速度快,以爲找到了原因,結果很失望,通過電子的同事,把EMMC對換了一下,開機速度還是沒有變化,快的還是快,慢的還是這麼慢,暈,白高興了一場,但至少也發現了EMMC讀寫速度是不一樣的,至少不是一無所獲。折騰了一天,也就得到個這樣的結果!!!

        過來一段時間以後,發現W的手機也變好了,28秒就能開機起來了,這是多麼興奮的是呀,不用解,問題就好了!可惜好景不長,沒過多久,發現W的手機開機時間又變回33秒了,這還真讓人鬱悶,於是用抓Log看下,結果就詫異了,從SurfaceFlinger is starting到Boot is finished用是時間還是17秒左右,並沒有變長呀!這是什麼原因呢?同過實時的抓取LOG發現,28秒能開機起來的時候,Boot is finished這句LOG一打出,解到了解鎖界面,但33秒是,卻還等了一會纔有解鎖界面,難怪!一問,才知道他們在Boot is finished加了一句usleep(5*1000*1000),原因是不這樣做,解鎖在開機起來後滑不動或者會卡頓,所以加了5秒的延遲。這我們當然是不同意的了!

       一個開機啓動折騰了將近一個月,時快試慢,希望以後別這邊慢,能夠保持這樣的速度。雖然汗水中伴着有失望、有痛苦,但自己還是學到了東西,至少知道做事情一定要堅持,面對問題時,視野一定要開闊,要考慮各種情況。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章