怎麼計算apk的啟動時間?
利用python或者直接用adb命令怎麼計算apk的啟動時間呢?就是計算從點擊圖標到apk完全啟動所花費的時間。比如,對遊戲來說就是點擊遊戲圖標到進入到登錄界面的這段時間。
已知的兩種方法貌似可以獲取,但是感覺結果不準確:一種是,adb shell am start -w packagename/activity,這個可以得到兩個值,ThisTime和TotalTime,不知道兩個有什麼區別,而且與實際啟動時間不匹配,兩者相加都可能比實際啟動時間小(測試遊戲的時候差別更大);另外一種是通過adb logcat的方式,感覺獲取的結果也與實際有差別。
終於有空來填坑啦。關於應用啟動速度,@Gracker已經回答的很完善了。我補充下「adb shell am start -W 」這條命令得出的三個時間是如何計算出來的,了解了這個也就清楚了究竟哪個時間更准了。
startTime記錄的剛準備調用startActivityAndWait()的時間點,endTime記錄的是startActivityAndWait()函數調用返回的時間點,WaitTime = startActivityAndWait()調用耗時。
ThisTime、TotalTime的計算在frameworksaseservicescorejavacomandroidserveramActivityRecord.java文件的reportLaunchTimeLocked()函數中。
我們來解釋下代碼里curTime、displayStartTime、mLaunchStartTime三個時間變數。curTime表示該函數調用的時間點.
displayStartTime表示一連串啟動Activity中的最後一個Activity的啟動時間點.
mLaunchStartTime表示一連串啟動Activity中第一個Activity的啟動時間點.正常情況下點擊桌面圖標只啟動一個有界面的Activity,此時displayStartTime與mLaunchStartTime便指向同一時間點,此時ThisTime=TotalTime。另一種情況是點擊桌面圖標應用會先啟動一個無界面的Activity做邏輯處理,接著又啟動一個有界面的Activity,在這種啟動一連串Activity的情況下(知乎的啟動就是屬於這種情況),displayStartTime便指向最後一個Activity的開始啟動時間點,mLaunchStartTime指向第一個無界面Activity的開始啟動時間點,此時ThisTime!=TotalTime。這兩種情況如下圖:
在上面的圖中,我用①②③分別標註了三個時間段,在這三個時間段內分別幹了什麼事呢?在第①個時間段內,AMS創建ActivityRecord記錄塊和選擇合理的Task、將當前Resume的Activity進行pause;
在第②個時間段內,啟動進程、調用無界面Activity的onCreate()等、pause/finish無界面的Activity; 在第③個時間段內,調用有界面Activity的onCreate、onResume;看到這裡應該清楚 ThisTime、TotalTime、WaitTime三個時間的關係了吧。WaitTime就是總的耗時,包括前一個應用Activity pause的時間和新應用啟動的時間;ThisTime表示一連串啟動Activity的最後一個Activity的啟動耗時;TotalTime表示新應用啟動的耗時,包括新進程的啟動和Activity的啟動,但不包括前一個應用Activity pause的耗時。也就是說,開發者一般只要關心TotalTime即可,這個時間才是自己應用真正啟動的耗時。
Event log中TAG=am_activity_launch_time中的兩個值分表表示ThisTime、TotalTime,跟通過「adb shell am start -W 」得到的值是一致的。
最後再說下系統根據什麼來判斷應用啟動結束。我們知道應用啟動包括進程啟動、走Activity生命周期onCreate/onResume等。在第一次onResume時添加窗口到WMS中,然後measure/layout/draw,窗口繪製完成後通知WMS,WMS在合適的時機控制界面開始顯示(夾雜了界面切換動畫邏輯)。記住是窗口界面顯示出來後,WMS才調用reportLaunchTimeLocked()通知AMS Activity啟動完成。
最後總結一下,如果只關心某個應用自身啟動耗時,參考TotalTime;如果關心系統啟動應用耗時,參考WaitTime;如果關心應用有界面Activity啟動耗時,參考ThisTime。事實上是可以準確計算的.但是要分場景.
但是要分開遊戲和應用. 大家都知道,在Android中,遊戲開發和應用開發是兩碼事.所以我們需要分開來說.1. 應用啟動.
我們平時在寫應用的時候,一般會指定一個mainActivity,用戶在桌面上點擊這個Activity的時候,系統會直接起這個Activity. 我們知道Activity在啟動的時候會走onCreate/onStart/onResume.這幾個回調函數.許多書里講過,當執行完onResume函數之後,應用就顯示出來了...其實這是一種不準確的說法,因為從系統層面來看,一個Activity走完onCreate/onStart/onResume這幾個生命周期之後,只是完成了應用自身的一些配置,比如window的一些屬性的設置/ View樹的建立(只是建立,並沒有顯示,也就是說只是調用了inflate而已) . 後面ViewRootImpl還會調用兩次performTraversals ,初始化Egl以及measure/layout/draw.等.所以我們定義一個Android應用的啟動時間, 肯定不能在Activity的回調函數上下手.而是以用戶在手機屏幕上看到你在onCreate的setContentView中設置的layout完全顯示為準,也就是我們常說的應用第一幀.上面扯得有點遠,不感興趣的話可以不看,下面直接說方法.
題主說的adb shell am start -w packagename/activity,是可以完全應用的啟動時間的.不過也要分場景.1.1 應用第一次啟動
也就是我們常說的冷啟動,這時候你的應用程序的進程是沒有創建的. 這也是大部分應用的使用場景.用戶在桌面上點擊你應用的icon之後,首先要創建進程,然後才啟動mainActivity.這時候adb shell am start -w packagename/activity 返回的結果,就是標準的應用程序的啟動時間:? adb shell am start -W com.meizu.media.painter/com.meizu.media.painter.PainterMainActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.meizu.media.painter/.PainterMainActivity }
Status: ok
Activity: com.meizu.media.painter/.PainterMainActivity
ThisTime: 355
TotalTime: 355
WaitTime: 365
Complete
總共返回了三個結果,我們以WaitTime為準. (關於ThisTime/TotalTime/WaitTime的區別,各位可以自己去看源碼.這裡就不詳細說了). WaitTime會返回從startActivity到應用第一幀完全顯示這段時間.
1.2 應用非第一次啟動
如果是你按Back鍵,並沒有將應用進程殺掉的話,那麼執行上述命令就會快一些,因為不用創建進程了,只需要啟動一個Activity即可。這也就是我們說的應用熱啟動。2. 遊戲啟動
遊戲啟動的話,就不適用用命令行的方法來啟動了,因為從用戶點擊桌面圖標到登錄界面,既有系統的部分也有遊戲自己的部分。2.1 系統部分
遊戲也有一個Activity,所以啟動的時候還是會去啟動這個Activity,所以系統啟動部分也就是用戶點擊桌面桌面響應到這個Activity啟動。2.2 遊戲部分
一般遊戲的主Activity啟動後,還會做一些比較耗時的事情,這時候你看到的界面是不能操作的,比如:載入遊戲數據、聯網更新數據、讀取和更新配置文件、遊戲引擎初始化等操作。從遊戲開發的角度來看,到了真正用戶能操作的界面才算是一個遊戲真正載入完成的時間。那麼這個時間,就得使用Log來記錄了,因為載入遊戲數據、聯網更新數據、讀取和更新配置文件、遊戲引擎初始化這些操作,都是遊戲自己的邏輯,與系統無關,所以得由遊戲自己定義載入完成的點。3. 準確性
計算機最讓人著迷的一點就是其準確性,1+1永遠等於2,啟動耗時多久就是多久,每一次可能不一樣,但每一次的時間都是這一次的準確時間。一些愚見,有想法可以一起交流我一般用wp上的stopwatch這個app(逃
題主所說的thistime或者logcat中 eventslog的lauchtime都是從startActivity開始算起,你也發現了實際的時間和這個有差距,差距的時間大部分就是Launch處理OnClick。
相對精確的時間從代碼上想看到,可以在InputDispatch中留樁記錄時間和Wms顯示Displayed的時間相減,就差不多等於實際的時間。(這個差距取決於tp事件的處理速度,一般很小)。
不過還可以提醒下題主,一般的平台代碼中都會有類似touchBurst(有touch事件就開核升頻)的功能,所以你am start /input 模擬點擊可能還會比實際的要慢,這個可以從systrace上對比下就清楚了。所以,如果想知道很精確的,高速相機+開發者模式打開指針位置,你就知道了。哈哈哈哈,這個真知道。想很準確嗎?高速攝像頭加壓力感測器啊。不然只能題主那樣定性地估算一下。那都是代碼級別的,跟實際肯定有差距。
5.0以上安卓系統有個Usage許可權能讓第三方應用調用android系統的app使用時間統計表,5.0以下的只能用服務去倒計時,匹配當前棧頂的activity的包名
對應用開發者來說,應該是從application的onCreate(或者attachBaseContext),一直到首個activity的onStart,這是可優化的時間
排名靠前的答案說得很不錯,也有人提到高清攝像機,再補充一個來完善下這個問題:adb shell screenrecord 錄屏功能有個參數可以記錄下錄製視頻的時間戳和幀數,可以人工看下。當然,為了自動化測試,無論是高清攝像機拍攝還是錄屏的視頻,都可以後期程序處理算出來啟動時間,原理都是看幀率。
用來看看開機時間?
更關心有無優化空間。安裝和啟動時間
推薦閱讀:
※Android中的Thread與AsyncTask的區別?
※Android應用怎麼繞過Fiddler等抓包工具?
※各位互聯網行業的大大們,你認識的最牛的安卓開發者是怎樣的?
※Android 已發行多年,移動 App 已經趨近飽和,那麼 Android 開發還會有那麼吃香嗎?
※Android 開發中,有哪些坑需要注意?