硬廣:《IOS性能調(diào)優(yōu)系列》第五篇,預(yù)計(jì)會(huì)有二十多篇,持續(xù)更新,歡迎關(guān)注。
之前四篇都是關(guān)注于內(nèi)存方面,分析了內(nèi)存泄漏、僵尸對象、內(nèi)存分配,本篇介紹Time PRofiler工具的使用,開始真正的“性能”調(diào)優(yōu)之旅。
Time Profiler還有之前介紹過的Leaks、Allocations工具,被戲稱為Instruments的救命三招,是當(dāng)應(yīng)用遇到問題時(shí)首先應(yīng)當(dāng)使用的三個(gè)工具。
Time Profiler幫助我們分析代碼的執(zhí)行時(shí)間,找出導(dǎo)致程序變慢的原因,告訴我們“時(shí)間都去哪兒了?”。
在使用Time Profiler之前,先看看原始的性能分析方法。
原始的性能分析方法
這種分析方法估計(jì)是很多開發(fā)人員第一時(shí)間想到的,寫個(gè)單元測試,在開始和結(jié)束的地方記錄時(shí)間。
示例代碼:
NSDate *stDate = [NSDate date];for(int i = 0; i < 999; i++){// do something }NSDate *endDate = [NSDate date];NSLog(@"time:%f", [endDate timeIntervalSinceDate:stDate]);
通過計(jì)算時(shí)差,可以算出中間消耗的時(shí)間,通過這種辦法可以一部分一部分的對可能出現(xiàn)性能瓶頸的代碼進(jìn)行分析。
這種方法的缺點(diǎn)有以下亮點(diǎn):
1、測試效率太低,很多性能瓶頸是很難預(yù)估到的,需要從上層到下層進(jìn)行逐步排除;
2、無法對界面渲染的效率進(jìn)行測試,找出界面性能瓶頸;
3、NSLog的分析不夠精確,可能在模擬器上由于開發(fā)設(shè)備性能速度快,無法明顯區(qū)分出性能瓶頸。
這也是使用Time Profiler工具的優(yōu)勢,能以極高的效率找出性能瓶頸。
使用Time Profiler的性能分析方法
Time Profiler分析原理:它按照固定的時(shí)間間隔來跟蹤每一個(gè)線程的堆棧信息,通過統(tǒng)計(jì)比較時(shí)間間隔之間的堆棧狀態(tài),來推算某個(gè)方法執(zhí)行了多久,并獲得一個(gè)近似值。其實(shí)從根本上來說與我們的原始分析方法異曲同工,只不過其將各個(gè)方法消耗的時(shí)間統(tǒng)計(jì)起來。
和使用 Instruments的其他工具一樣,點(diǎn)擊XCode的Product菜單Profile啟動(dòng)Instruments:
選擇Time Profiler工具開始測試,這時(shí)會(huì)自動(dòng)啟動(dòng)模擬器和Time Profiler錄制。
先進(jìn)行一些App的操作,讓Time Profiler收集足夠的數(shù)據(jù),尤其是你覺得那些有性能瓶頸的地方。
4、5、6所標(biāo)記的面板是需要關(guān)注的:
4是擴(kuò)展面板,用來跟蹤顯示堆棧;5是詳細(xì)地面板,可以從這里看到cpu運(yùn)行的時(shí)間都消耗在哪里;6是選項(xiàng)面板,可以用來設(shè)置Time Profiler的運(yùn)行參數(shù)。
通過對應(yīng)用的操作,可以在詳細(xì)面板中看到那些最耗時(shí)的操作是哪些,并可以逐行展開查看:
圖標(biāo)為黑色頭像的就是Time Profiler給我們的提示,有可能存在性能瓶頸的地方,可以逐漸向下展開,找到產(chǎn)生的根本原因。
比如我們通過分析,發(fā)現(xiàn)[CMTool getNewsTimeFromLong]這個(gè)時(shí)間格式化函數(shù)可能需要優(yōu)化。
當(dāng)然這里只是舉一個(gè)例子,性能調(diào)優(yōu)應(yīng)該首先從整體到細(xì)節(jié)的順序進(jìn)行,才能收到最明顯的效果。
Time Profiler參數(shù)設(shè)置
這里邊幾個(gè)選項(xiàng)的含義如下:
Separate by Thread: 每個(gè)線程應(yīng)該分開考慮。只有這樣你才能揪出那些大量占用CPU的"重"線程
Invert Call Tree: 從上倒下跟蹤堆棧,這意味著你看到的表中的方法,將已從第0幀開始取樣,這通常你是想要的,只有這樣你才能看到CPU中話費(fèi)時(shí)間最深的方法.也就是說FuncA{FunB{FunC}} 勾選此項(xiàng)后堆棧以C->B-A 把調(diào)用層級最深的C顯示在最外面
Hide Missing Symbols: 如果dSYM無法找到你的app或者系統(tǒng)框架的話,那么表中看不到方法名只能看到十六進(jìn)制的數(shù)值,如果勾線此項(xiàng)可以隱藏這些符號,便于簡化數(shù)據(jù)
Hide System Libraries: 勾選此項(xiàng)你會(huì)顯示你app的代碼,這是非常有用的. 因?yàn)橥ǔD阒魂P(guān)心cpu花在自己代碼上的時(shí)間不是系統(tǒng)上的
Show Obj-C Only: 只顯示oc代碼 ,如果你的程序是像OpenGl這樣的程序,不要勾選側(cè)向因?yàn)樗锌赡苁荂++的
Flatten Recursion: 遞歸函數(shù), 每個(gè)堆棧跟蹤一個(gè)條目
Top Functions: 一個(gè)函數(shù)花費(fèi)的時(shí)間直接在該函數(shù)中的總和,以及在函數(shù)調(diào)用該函數(shù)所花費(fèi)的時(shí)間的總時(shí)間。因此,如果函數(shù)A調(diào)用B,那么A的時(shí)間報(bào)告在A花費(fèi)的時(shí)間加上B花費(fèi)的時(shí)間,這非常真有用,因?yàn)樗梢宰屇忝看蜗碌秸{(diào)用堆棧時(shí)挑最大的時(shí)間數(shù)字,歸零在你最耗時(shí)的方法。
上面的參數(shù)在實(shí)踐中合理設(shè)置,也沒有什么太多技巧,就是通過數(shù)據(jù)的隱藏、顯示讓我們更關(guān)注于想找到的數(shù)據(jù)。
天下應(yīng)用,唯快不破!尤其是手機(jī)應(yīng)用,更應(yīng)該注意用戶體驗(yàn)和響應(yīng)速度。
記錄,為更好的自己!
新聞熱點(diǎn)
疑難解答
圖片精選