您好,登錄后才能下訂單哦!
【背景介紹】
雖然iPhone的性能越來(lái)越好,但app的功能也越來(lái)越復(fù)雜,性能從來(lái)都是移動(dòng)開(kāi)發(fā)的核心關(guān)注點(diǎn)之一。我們說(shuō)一個(gè)app性能好,不是簡(jiǎn)單指感覺(jué)運(yùn)行速度快,而應(yīng)該是指應(yīng)用啟動(dòng)快速、UI反饋?lái)憫?yīng)及時(shí)、列表滾動(dòng)操作流暢、內(nèi)存使用合理,當(dāng)然更不能出現(xiàn)簡(jiǎn)單的crash了。
那么iOS的性能測(cè)試是什么:資源消耗、內(nèi)存泄漏、流量消耗、耗電功率、渲染效果、加載時(shí)間。。。
以下將結(jié)合iPhone瀏覽器從啟動(dòng)時(shí)間、加載時(shí)間、內(nèi)存占用、CPU和流暢度等維度介紹如何完成一個(gè)iOS app的性能測(cè)試。其中會(huì)用到Apple的性能分析神器”Instruments”。
一、啟動(dòng)時(shí)間
移動(dòng)應(yīng)用的啟動(dòng)時(shí)間是用戶體驗(yàn)的一個(gè)重要方面,蘋果一直建議盡可能的縮短啟動(dòng)時(shí)間,防止用戶不愿意使用它們。對(duì)于瀏覽器而言,由于程序啟動(dòng)時(shí)還會(huì)有教育頁(yè)和閃屏的下發(fā),因此啟動(dòng)時(shí)間的獲取顯得尤為重要。
啟動(dòng)時(shí)間分為冷啟動(dòng)時(shí)間和熱啟動(dòng)時(shí)間,所謂的“冷啟動(dòng)”,就是一個(gè)完全沒(méi)有運(yùn)行的應(yīng)用的啟動(dòng)時(shí)間,與熱啟動(dòng)(應(yīng)用已經(jīng)在后臺(tái)運(yùn)行,某個(gè)事件將其帶至前臺(tái))相比,由于此時(shí)系統(tǒng)尚未建立緩存,因此冷啟動(dòng)往往要較平時(shí)(熱啟動(dòng))耗費(fèi)更長(zhǎng)的時(shí)間。
要獲取準(zhǔn)確的app啟動(dòng)所需時(shí)間,最簡(jiǎn)單的就是通過(guò)性能打點(diǎn)的方法。首先在main.c中添加如下代碼:
CFTimeInterval startTimeLog;
int main(int argc, char *argv[]) {
startTimeLog = CACurrentMediaTime();
然后在AppDelegate的回調(diào)方法application:didFinishLaunchingWithOptions中添加:
dispatch_async(dispatch_get_main_queue(), ^{
CGFloat launchTime = CACurrentMediaTime() - startTimeLog;
NSLog(@"launch: %f", launchTime);
});
可能你會(huì)疑問(wèn)為什么這樣可以獲得系統(tǒng)啟動(dòng)的時(shí)間,因?yàn)檫@個(gè)dispatch_async中提交的工作會(huì)在app主線程啟動(dòng)后的下一個(gè)runloop中運(yùn)行,此時(shí)app已經(jīng)完成了載入并且將要顯示第一幀畫面,也就是系統(tǒng)會(huì)運(yùn)行到-[UIApplication _reportAppLaunchFinished]之前。
下圖是用Instruments工具Time Profiler跑的調(diào)用棧信息。
圖1
所以使用Time Profiler同樣可以查看app的啟動(dòng)時(shí)間,具體方法如下:
1. Instruments->Time Profiler
2. Profiler你的app
3. 切換到CPU strategy view,找到你的app啟動(dòng)的第一幀
4. 搜索-[UIApplication _reportAppLaunchFinished]的最后一幀,即可算出啟動(dòng)時(shí)間(圖中為_(kāi)reportMainScreenUpdateFinished:)
為了拿到真實(shí)的用戶數(shù)據(jù),追蹤版本之間的數(shù)據(jù)變化,目前瀏覽器線上版本中啟動(dòng)時(shí)間已作為性能埋點(diǎn)上傳,這樣我們就可以計(jì)算出每日不同機(jī)型不同OS的平均啟動(dòng)時(shí)間,以幫助更加實(shí)時(shí)有效的監(jiān)控線上的性能質(zhì)量數(shù)據(jù)。
二、網(wǎng)頁(yè)加載時(shí)間
據(jù)Google Analytics數(shù)據(jù),目前移動(dòng)網(wǎng)頁(yè)平均加載時(shí)間至少需要7秒,Google的目標(biāo)是把這個(gè)時(shí)間降至1秒,因?yàn)閰⒖糔ielsan Norman Group 的調(diào)查研究結(jié)果:如果移動(dòng)網(wǎng)頁(yè)加載時(shí)間超過(guò) 1 秒,用戶就不愿停留在頁(yè)面上了。
在目前的技術(shù)基礎(chǔ)上,在幾百毫秒內(nèi)加載數(shù)個(gè)網(wǎng)頁(yè)幾乎是不可能實(shí)現(xiàn)的,但在1秒內(nèi)完成移動(dòng)網(wǎng)頁(yè)首頁(yè)內(nèi)容加載是有可能的,而剩余內(nèi)容則慢慢加載。因此網(wǎng)頁(yè)加載首屏展現(xiàn)時(shí)間成為了衡量手機(jī)瀏覽器的一個(gè)重要性能指標(biāo),計(jì)算方法為從開(kāi)始加載網(wǎng)頁(yè)到首屏內(nèi)容全部展現(xiàn)所用的時(shí)間。
網(wǎng)頁(yè)加載時(shí)間同樣可以基于打點(diǎn)的方法獲得。移動(dòng)網(wǎng)頁(yè)的加載都是從Webview的url請(qǐng)求開(kāi)始的,webview的操作都會(huì)有UIWebviewDelegate的方法代理完成,因此通過(guò)對(duì)webview代理方法的研究(見(jiàn)下圖),選取正確的方法作為開(kāi)始時(shí)間和結(jié)束時(shí)間,即可獲取網(wǎng)頁(yè)的首屏加載展現(xiàn)時(shí)間和網(wǎng)頁(yè)加載完成時(shí)間。
圖2
對(duì)于競(jìng)品,我們則可以在越獄機(jī)型上通過(guò)動(dòng)態(tài)庫(kù)hook的方法進(jìn)行加載時(shí)間的計(jì)算,簡(jiǎn)單介紹如下:
1. class-dump-z命令獲得應(yīng)用程序的類信息
a) 導(dǎo)出設(shè)備上預(yù)裝應(yīng)用的類信息(/Applications)
b) 導(dǎo)出從AppStore下載的app的類信息,需要clutch命令破解(/var/mobile/Applications)
2. 用GDB或Cycript進(jìn)行運(yùn)行時(shí)分析(Cycript是一個(gè)理解Objective-C語(yǔ)法的javascript解釋器),hook當(dāng)前運(yùn)行的進(jìn)程,打印當(dāng)前運(yùn)行的viewcontroller及對(duì)應(yīng)的方法名;
3. 動(dòng)態(tài)庫(kù)注入,執(zhí)行method swizzling,在對(duì)應(yīng)的方法中打印時(shí)間日志
關(guān)于如何使用運(yùn)行時(shí)分析及動(dòng)態(tài)庫(kù)注入,這里就不詳細(xì)說(shuō)明了。
當(dāng)然,加載時(shí)間的查看也可以借助于Apple的性能分析神器Instruments。當(dāng)我們發(fā)現(xiàn)App有點(diǎn)卡的時(shí)候,就可以通過(guò)Time Profiler來(lái)查看耗時(shí)在哪里,如圖突出的范圍就是步驟消耗的時(shí)間。
圖3
在這里同時(shí)分享一個(gè)基于攝像+分析的快速進(jìn)行啟動(dòng)時(shí)間和加載時(shí)間計(jì)算的方法。當(dāng)前手機(jī)的攝像頭基本上都支持高FPS的拍攝,拍下來(lái)的MP4文件可以通過(guò)免費(fèi)的Avidemux工具來(lái)看具體的幀信息,也可以看到幀的時(shí)間戳,根據(jù)拍攝的格式,目前我測(cè)試的視頻可以達(dá)到30毫秒級(jí)別,完全滿足性能測(cè)試的需求。
三、內(nèi)存測(cè)試
iOS系統(tǒng)中內(nèi)存限制是較為嚴(yán)格的,因此內(nèi)存優(yōu)化也就成了iOS app一直以來(lái)的難題。關(guān)于內(nèi)存測(cè)試的方法有很多,可以直接用Xcode真機(jī)Debug查看,也可以通過(guò)Instruments中內(nèi)存相關(guān)的模板Activity Monitor獲得。
圖4 Xcode調(diào)試查看內(nèi)存
圖5 Activity Monitor查看內(nèi)存
在實(shí)際性能測(cè)試中,內(nèi)存測(cè)試往往會(huì)分場(chǎng)景進(jìn)行,通過(guò)腳本模擬用戶常用場(chǎng)景操作,分析該場(chǎng)景下的內(nèi)存占用情況。
1. 指定run.js腳本測(cè)試
$ instruments -w ${UDID} -t ${template} ${APP} -e UIASCRIPT ${script} > .input.log
2. 解析ActivityMonitor模板的trace文件,生成對(duì)應(yīng)的json格式數(shù)據(jù)
$ instruments_parser -p process_name -i result.trace
其中一個(gè)json塊數(shù)據(jù)格式參照如下:
{
"Threads" : 12,
"UnixSyscalls" : 14314,
"Command" : "com.baidu.ime.Ba",
"VirtualSize" : 718213120,
"ContextSwitches" : 5774,
"Ports" : 166,
"PageIns" : 4881,
"Shared" : 12976128,
"PPID" : 1,
"CPUUsage" : 0,
"UID" : 501,
"TotalMicroSeconds" : 307788,
"Timestamp" : 1421818303.125269,
"VPrivate" : 29028352,
"Date" : "2015-01-21 13:31:43:125",
"MessagesSent" : 4042,
"PID" : 721,
"TotalSeconds" : 1,
"Private" : 9338880,
"PGID" : 721,
"MachSyscalls" : 7186,
"ResidentSize" : 39362560,
"Architecture" : 16777228,
"Faults" : 19274,
"MessagesReceived" : 1709
}
3. 統(tǒng)計(jì)ResidentSize、VirtualSize字段,使用python的matplotlib圖形庫(kù)生成內(nèi)存變化圖表。
然而對(duì)于內(nèi)存測(cè)試,如果你覺(jué)得只是需要跟蹤app的內(nèi)存使用情況,那么你就錯(cuò)了。一套完整的內(nèi)存管理測(cè)試方案需要關(guān)注的點(diǎn)其實(shí)還有很多,比如使用Leaks分析內(nèi)存泄漏,使用Allocations分析內(nèi)存浪費(fèi),使用Zombie分析野指針,使用VMTracker測(cè)試虛擬內(nèi)存,代碼中是否仍使用ARC機(jī)制等等。
其中關(guān)于虛擬內(nèi)存的測(cè)試或許是最容易被忽略的,瀏覽器就曾經(jīng)發(fā)現(xiàn)過(guò)實(shí)際內(nèi)存占用不高,但虛擬內(nèi)存上漲很快,從而導(dǎo)致app因?yàn)閮?nèi)存不足被系統(tǒng)kill的問(wèn)題。
那么如何分析app的虛擬內(nèi)存呢?我們可以通過(guò)Instruments的VM Tracker進(jìn)行查看。VM Tracker主要用于記錄app的虛擬內(nèi)存分配,該模板會(huì)顯示app中分配了多大的虛擬內(nèi)存空間,其中多少是Dirty的內(nèi)存,有多少是被映射到實(shí)際物理內(nèi)存中,并且可以顯示詳細(xì)的虛擬內(nèi)存分配情況。
圖6 VM Tracker查看虛擬內(nèi)存
關(guān)于上圖中的dirty size,這里介紹一下dirty & clean的概念。
在程序使用的內(nèi)存page中,iOS區(qū)分兩種內(nèi)存,一種為clean,一種為dirty。
clean page的概念為所有可以被廢棄并且重新生成的page,例如二進(jìn)制代碼等從磁盤讀取的文件,例如未曾讀寫過(guò)的page,或者被標(biāo)識(shí)為可擦除的內(nèi)存等。
dirty page的概念為無(wú)法重新生成的page,即app生成的,并且已經(jīng)寫入過(guò)的page,例如使用malloc分配的heap內(nèi)存,全局變量,stack內(nèi)存等。
當(dāng)系統(tǒng)發(fā)現(xiàn)可用內(nèi)存較少時(shí),會(huì)將resident中的clean page進(jìn)行清除,當(dāng)有需要使用時(shí)直接從磁盤讀取就行。系統(tǒng)不能卸載掉dirty memory,因?yàn)閕OS是沒(méi)有內(nèi)存置換機(jī)制的。當(dāng)dirty memory達(dá)到一個(gè)上限時(shí),應(yīng)用會(huì)被kill,由系統(tǒng)回收內(nèi)存。
說(shuō)到上限,這里可能有人會(huì)問(wèn),在iOS設(shè)備中打開(kāi)很多app后,打開(kāi)被測(cè)app,該app占用內(nèi)存的上限能達(dá)到多少呢?我們可以通過(guò)demo app,手動(dòng)malloc內(nèi)存,也可以通過(guò)instruments查看,觀察內(nèi)存警告時(shí),App被kill時(shí)的日志輸出。
下表列出了對(duì)各種設(shè)備進(jìn)行測(cè)試后得到的數(shù)值,供大家參考。
圖7 不同設(shè)備內(nèi)存占用限制
四、CPU測(cè)試
CPU測(cè)試的方法和內(nèi)存較為類似,可以通過(guò)Instruments中的Activity Monitor模板查看,也可以通過(guò)客戶端打點(diǎn)的方法獲取。
在瀏覽器性能測(cè)試中,重點(diǎn)模塊的CPU測(cè)試還需要針對(duì)不同機(jī)型不同Architecture指令集進(jìn)行兼容。例如在iPhone瀏覽器播放內(nèi)核庫(kù)的測(cè)試中就需要兼容armv7、armv7s、arm64、i386、x86-64五種CPU上都經(jīng)過(guò)測(cè)試。
五、流暢度
對(duì)于瀏覽器而言,會(huì)存在著較多網(wǎng)頁(yè)瀏覽、動(dòng)畫顯示等操作,這時(shí)是否存在卡頓對(duì)于用戶體驗(yàn)就顯得較為重要。關(guān)于流暢度的測(cè)試我們可以通過(guò)使用instruments的core animation工具,瀏覽網(wǎng)頁(yè)或加載動(dòng)畫,查看fps的幀數(shù)。一般而言,當(dāng)用戶操作時(shí),如果fps幀數(shù)小于40,則說(shuō)明存在卡頓的情形。
圖8 Core Animation查看fps幀數(shù)
百度將于近期推出技術(shù)類圖書《如何高效地開(kāi)發(fā)一款高質(zhì)量的移動(dòng)APP》(名稱待定),這將是百度首次技術(shù)輸出,選題聚焦在移動(dòng)互聯(lián)網(wǎng)領(lǐng)域,內(nèi)容覆蓋APP開(kāi)發(fā)、部署、測(cè)試、分發(fā)、變現(xiàn)、監(jiān)控和數(shù)據(jù)分析的全過(guò)程。幫助移動(dòng)APP開(kāi)發(fā)者,更好的了解百度的領(lǐng)先技術(shù)、項(xiàng)目經(jīng)驗(yàn)以及自主研發(fā)工具等。
作為業(yè)界領(lǐng)先的移動(dòng)應(yīng)用一站式測(cè)試服務(wù)平臺(tái),百度MTC覆蓋移動(dòng)應(yīng)用從開(kāi)發(fā)、測(cè)試到上線、運(yùn)營(yíng)的整個(gè)生命周期,為廣大開(kāi)發(fā)者在移動(dòng)應(yīng)用開(kāi)發(fā)測(cè)試過(guò)程中面臨的成本、技術(shù)和效率問(wèn)題提供解決方案。本次出書稿件將陸續(xù)在MTC學(xué)院發(fā)表(http://mtc.baidu.com/academy/article),同步覆蓋其他技術(shù)論壇,并將在今年上半年集結(jié)成冊(cè),正式出版發(fā)行,敬請(qǐng)期待吧!
>>如有問(wèn)題,歡迎與我溝通
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。