先來一發(fā)蘋果官網(wǎng)上Instruments User Guide厦幅,其實沒啥用舌缤,英語不好的也懶得去看。(反正我是看不懂)
關(guān)于Instruments有網(wǎng)友如是說的:“一句話: 內(nèi)存開銷黔帕、運行速度代咸、內(nèi)存泄露 and so on”。
如此簡單的回答肯定打發(fā)不了咱們各位看官和面試官成黄,當然上述表達和下邊的網(wǎng)友總結(jié)的意思是一樣的:
問:您一般是怎么使用Instruments的呐芥?
這個問題也就是考察下你經(jīng)驗如何了, Instruments里面工具很多,也沒必要逐一說明,挑幾個常用的說下就好:
Time Profiler:分析代碼的執(zhí)行時間逻杖,找出導致程序變慢的原因。
Zombies:檢查是否訪問了僵尸對象,但是這個工具只能從上往下檢查,不智能
Allocations:用來檢查內(nèi)存分配,寫算法的那批人也用這個來檢查
Leaks:檢查內(nèi)存,看是否有內(nèi)存泄露
還有對Instruments這么理解的思瘟,說的也不錯:Instruments的價值在于荸百,它使我們深刻理解我們代碼的內(nèi)部運作。
好了滨攻,那么就開始我們自己的Instruments之旅吧够话,揭開神秘面紗。
注:本文大部分篇幅將講述Allocations光绕、Leaks女嘲、Time Profiler、Zombies這四項诞帐,因為是經(jīng)常用到的欣尼,其他的可能簡單介紹或者一帶而過。
關(guān)于Instruments的概述請參考Instruments概述景埃,可以整體的理解一下Instruments媒至。
首先我們要知道怎么打開這個Instruments:在xcode中有好幾種打開的方式,具體如下:
1谷徙、
2拒啰、
3、長按啟動按鈕完慧,選擇Profile
Instruments頁面如下谋旦,里面全是英文,筆者為大家用有道翻譯了一下屈尼,哪里不對册着,希望大家告知,我進行修改脾歧。
其實我們可以看到xcode開發(fā)人員的用心甲捏,一些圖片上邊的標志我們一看就能明白是什么意思,例如能量診斷鞭执,其實就是手機上邊的電池嘛??司顿,還有泄漏,就是一個管子兄纺,有水滴??滴下來了大溜,就是泄漏的意思。還有網(wǎng)絡(luò)估脆,就是一個信號塔發(fā)射信號的意思钦奋。有的看不懂沒關(guān)系,我這不是給大家翻譯了嘛。
另外有的時候Instruments的啟動按鈕是啟動不了的付材,這怎么辦呢朦拖,有大神給提供了一種解決方案:Instruments啟動按鈕不可點。(在這里謝謝標哥大神厌衔,雖然你也不看我的博客哈哈)
大概的解決方案就是:各種重啟贞谓。手機關(guān)機、重啟葵诈,同時將Xcode關(guān)掉,然后重新打開Xcode祟同,然后重新將手機與電腦連接作喘,再打開Instrument,點擊Core Animation晕城,切換到當前的手機泞坦,發(fā)現(xiàn)可以正常點擊了。
在這里有必要說一句砖顷,這19個性能檢測的工具贰锁,有的可以在模擬器上邊進行檢測,有的是不可以的滤蝠。如果選擇使用ios模擬器豌熄,那么它監(jiān)控的就會是你的mac,和真機還是有區(qū)別的物咳,譬如這個電池就應(yīng)該用真機檢測锣险,模擬器的電池沒啥可測的。而我們的目的是手機app,當然邀摆,所有的項目都是都可以在真機上檢測的冗酿。建議大家盡量在真機上用Istrunments。下邊我們就逐一看看這19個性能檢測是怎么操作的击蹲,到底怎么就檢測了呢上鞠,檢測出來的都是什么東西呢际邻,會得到什么樣的結(jié)果呢芍阎,我們拭目以待。
1骗露、Blank:
空白的萧锉,沒啥可說的柿隙。
2禀崖、Activity Monitor 活動監(jiān)視器:
監(jiān)測CPU螟炫、內(nèi)存昼钻、硬盤和網(wǎng)絡(luò)使用情況然评,還能檢測所有的進程碗淌,檢測父/子進程的層次贯莺。默認情況下顯示:虛擬內(nèi)存大小,cup總使用量魂莫,cup用戶所使用的占用比耙考,cpu系統(tǒng)使用占用比倦始。推薦學習小白學習Activity Monitor鞋邑。
第1部分是profile的表頭枚碗,啟動肮雨、暫停怨规、項目名稱波丰、運行時間等等信息都可以在上邊找到。
第2部分是左邊是性能檢測的項目名稱,右邊以豎形條形式展示運行過程中數(shù)據(jù)值的大小,比較直觀惧磺。
第3部分是具體的性能數(shù)值磨隘,可以選擇Details(詳細信息)和Console(控制臺)番捂,可以看到具體的詳細信息设预。
3鳖枕、Allocations 分配:
(1龇魏烫!重點之一來了?既蟆糊治!來得如此之快井辜,還叫人有些不適應(yīng)呢)
為什么我們要使用這個Allocations粥脚,參考Alloactions簡單使用刷允。文章中介紹了原因:
Allocations 的頁面如下所示:
1:堆區(qū)內(nèi)存和虛擬內(nèi)存占用圖
2:堆區(qū)內(nèi)存占用圖
3:虛擬內(nèi)存跟蹤圖
4:選擇使用不同的形式展示內(nèi)存占用情況
5:勾選讓上面曲線圖展示對應(yīng)內(nèi)存占用情況
6:持久分配的內(nèi)存所占字節(jié)數(shù)(未釋放)即該類對象在內(nèi)存中占得總內(nèi)存
7:持久創(chuàng)建的對象個數(shù)(未釋放)即該對象存在于內(nèi)存中的個數(shù)
8:臨時分配的對象個數(shù)(未釋放)即存在過已經(jīng)被回收的對象的個數(shù)
9:分配的所有內(nèi)存所占字節(jié)數(shù)(未釋放)
10:創(chuàng)建的對象總數(shù)(未釋放)
11:設(shè)置面板糯而,不同的設(shè)置使左邊有不同展示效果
如上圖并不能很好的了解每個方法所占用的內(nèi)存情況熄驼,接下來我們點擊4的call Trees如下圖設(shè)置:
接下來我們根據(jù)內(nèi)存泄漏的情況對內(nèi)存分配進行分析诺祸,內(nèi)存泄漏分兩種:
第一種:為對象A申請了內(nèi)存空間序臂,之后再也沒用到A奥秆,也沒有釋放A導致內(nèi)存泄漏构订。這種是Leaked Memory內(nèi)存泄漏悼瘾。
第二種:類似于遞歸卸勺,不斷的申請內(nèi)存導致的內(nèi)存泄漏曙求。根據(jù)下邊的鏈接文章我們知道這種情況就是Abandoned Memory被遺棄的內(nèi)存悟狱。
說到這里大家可以去看看這篇文章iOS Instruments挤渐,名字雖然起的很一般,但是講了Allocations的前因后果软免。當然,下文我也拿來借鑒了宣蔚。在此胚委,謝謝文章作者luobs。
第二種情況根據(jù)以下圖的操作可以清晰的找到對應(yīng)的問題代碼硅急,當然不一定是我們自己代碼的原因营袜,也有可能是系統(tǒng)框架的問題荚板。
下邊是關(guān)于尋找這個Abandoned Memory被遺棄的內(nèi)存的方法:
該方法筆者沒有親測,但是看著挺可靠的唧席,具體的步驟告訴了袱吆,按照步驟一步一步的走下來應(yīng)該就能找到被遺棄的內(nèi)存(看到這個“被遺棄”的詞,就想起了《紀念碑谷》)
4蓬衡、Automation:自動化??
UI 自動測試是iOS 中重要的附加功能狰晚,它由名為“Automation”的新的工具對象支持壁晒。Automation工具的腳本是用JavaScript語言編寫,主要用于分析應(yīng)用的性能和用戶行為携取,模仿/擊發(fā)被請求的事件雷滋,利用它可以完成對被測應(yīng)用的簡單的UI測試及相關(guān)功能測試晤斩。
簡單的說就是自己寫JS腳本進行測試。(最好了解JS語言最好了烹俗,不了解的這個Automation其實有點雞肋)
可以參考下邊這篇文章借鑒他人UI Automation幢妄。
5、Cocoa Layout:自動布局?
Cocoa Layout可以應(yīng)用于iOS模擬器和Cocoa桌面應(yīng)用榕吼,但是不能和連接的iOS設(shè)備一起使用羹蚣。Cocoa Layout提供了一個與NSLayoutConstraint類的實例有關(guān)的所有事件的時間軸,這一點和回溯(backtrace)很像胁出。
關(guān)于這項內(nèi)容網(wǎng)上資料并不多全蝶,大家可以參考利用Cocoa Layout 檢視自動布局
6、Core Animation:核心動畫?
?在網(wǎng)上查資料丈冬,大部分都是關(guān)于動畫怎么設(shè)置的往弓,和layer有關(guān)的動畫制作函似,即便前面加上Instruments撇寞,查出來的也是關(guān)于動畫制作的牌废。鸟缕。懂从。也是醉了侵贵。幸好我們同事之前總結(jié)過關(guān)于這方面的模燥,直接拿來用吧蔫骂。如果大家有相關(guān)的鏈接,希望能給提供一下补胚,謝謝了溶其。
這里我們需要知道這個Core Animation是干什么的,Core Animation工具是用來檢測Core Animation性能的厢绝。(看起來這句話好像說了等于沒說,不過從這句話里面我們可以看出加粗的Core Animation是我們網(wǎng)上查到的利用iOS做的動畫靶病,而前面沒有加粗的是咱們Istruments里面的Core Animation工具)
首先我們了解什么是FPS娄周。FPS:一秒鐘渲染多少幀 Frame Per Second = FPS驾凶。
Core Animation給我們提供了周期性的FPS调违,并且考慮到了發(fā)生在程序之外的動畫,界面滑動FPS可以進行測試虚婿。一般FPS是60左右,過于低的話需要進行優(yōu)化剧浸。根據(jù)下圖我們會發(fā)現(xiàn)唆香,過于低的數(shù)值是低于45。
看上圖,我們主要介紹右邊“設(shè)置”里面的相關(guān)內(nèi)容延柠。
Color Blended Layers混合過度繪制
這個選項基于渲染程度對屏幕中的混合區(qū)域進行綠到紅的高亮(也就是多個半透明圖層的疊加)贞间。由于重繪的原因整以,混合對GPU性能會有影響公黑,同時也是滑動或者動畫幀率下降的罪魁禍首之一人断。
這樣就能在模擬器上邊看到這個Color Blended Layers
GPU每一幀可以繪制的像素有一個最大限制(就是所謂的fill rate),這個情況下可以輕易地繪制整個屏幕的所有像素暇仲。但是如果由于重疊圖層的關(guān)系需要不停地重繪同一區(qū)域的話,掉幀就可能發(fā)生了桅狠。
GPU會放棄繪制那些完全被其他圖層遮擋的像素,但是要計算出一個圖層是否被遮擋也是相當復雜并且會消耗處理器資源漩符。同樣,合并不同圖層的透明重疊像素(即混合)消耗的資源也是相當客觀的闷沥。所以為了加速處理進程舆逃,不到必須時刻不要使用透明圖層路狮。任何情況下虫啥,你應(yīng)該這樣做:
給視圖的backgroundColor屬性設(shè)置一個固定的,不透明的顏色
設(shè)置opaque屬性為YES
注意:下邊的內(nèi)容為我們解釋了為什么在tableview性能優(yōu)化中我們提到的平衡CPU和GPU里面關(guān)于Core Animation的原因奄妨。
(關(guān)于CPU和GPU可以參考CPU與GPU)
如果用到了圖像涂籽,盡量避免透明除非非常必要。如果圖像要顯示在一個固定的背景顏色或是固定的背景圖之前砸抛,你沒必要相對前景移動,你只需要預填充背景圖片就可以避免運行時混色了直焙。
如果是文本的話柳骄,一個白色背景的UILabel(或者其他顏色)會比透明背景要更高效。
Color?Offscreen-Rendered Yellow(離屏渲染)
這里會把那些需要離屏渲染的圖層高亮成黃色箕般。這些圖層很可能需要用shadowPath或者shouldRasterize來優(yōu)化耐薯。
當圖層屬性的混合體被指定為在未預合成之前不能直接在屏幕中繪制時,屏幕外渲染就被喚起了丝里。屏幕外渲染并不意味著軟件繪制曲初,但是它意味著圖層必須在被顯示之前在一個屏幕外上下文中被渲染(不論CPU還是GPU)。圖層的以下屬性將會觸發(fā)屏幕外繪制:
1杯聚、圓角(當和maskToBounds一起使用時)
2臼婆、圖層蒙板
3、陰影
屏幕外渲染和我們啟用光柵化時相似幌绍,除了它并沒有像光柵化圖層那么消耗大颁褂,子圖層并沒有被影響到,而且結(jié)果也沒有被緩存傀广,所以不會有長期的內(nèi)存占用颁独。但是,如果太多圖層在屏幕外渲染依然會影響到性能伪冰。
有時候我們可以把那些需要屏幕外繪制的圖層開啟光柵化以作為一個優(yōu)化方式誓酒,前提是這些圖層并不會被頻繁地重繪。
對于那些需要動畫而且要在屏幕外渲染的圖層來說贮聂,你可以用CAShapeLayer靠柑,contentsCenter或者shadowPath來獲得同樣的表現(xiàn)而且較少地影響到性能。
Color Hits Greenand Misses Red(光柵化緩存圖層命中情況)
當使用shouldRasterizep屬性的時候吓懈,耗時的圖層繪制會被緩存歼冰,然后當做一個簡單的扁平圖片呈現(xiàn)。當緩存再生的時候這個選項就用紅色對柵格化圖層進行了高亮耻警。如果緩存頻繁再生的話隔嫡,就意味著柵格化可能會有負面的性能影響了甸怕。
Color Copied Images 拷貝的圖片
有時候寄宿圖片的生成意味著Core Animation被強制生成一些圖片,然后發(fā)送到渲染服務(wù)器畔勤,而不是簡單的指向原始指針。這個選項把這些圖片渲染成藍色扒磁。復制圖片對內(nèi)存和CPU使用來說都是一項非常昂貴的操作庆揪,所以應(yīng)該盡可能的避免。
Color Immediately ?顏色立即更新
通常Core Animation Instruments以每毫秒10次的頻率更新圖層調(diào)試顏色妨托。對某些效果來說缸榛,這顯然太慢了。這個選項就可以用來設(shè)置每幀都更新(可能會影響到渲染性能兰伤,而且會導致幀率測量不準内颗,所以不要一直都設(shè)置它)。
Color Misaligned ?Images(圖片的不正扯厍唬縮放)
-這里會高亮那些被縮放或者拉伸以及沒有正確對齊到像素邊界的圖片(也就是非整型坐標)均澳。這些中的大多數(shù)通常都會導致圖片的不正常縮放符衔,如果把一張大圖當縮略圖顯示找前,或者不正確地模糊圖像,那么這個選項將會幫你識別出問題所在判族。
Color OpenGL Fast Path?Blue
這個選項會對任何直接使用OpenGL繪制的圖層進行高亮躺盛。如果僅僅使用UIKit或者Core Animation的API,那么不會有任何效果形帮。如果使用GLKView或者CAEAGLLayer槽惫,那如果不顯示藍色塊的話就意味著你正在強制CPU渲染額外的紋理,而不是繪制到屏幕辩撑。
Flash Updated Regions(Core Graphics繪制的圖層)
-這個選項會對重繪的內(nèi)容高亮成黃色(也就是任何在軟件層面使用Core Graphics繪制的圖層)界斜。這種繪圖的速度很慢。如果頻繁發(fā)生這種情況的話合冀,這意味著有一個隱藏的bug或者說通過增加緩存或者使用替代方案會有提升性能的空間锄蹂。
7、Core Data ?核心數(shù)據(jù)?
?依舊是我們在網(wǎng)上查找資料水慨,好多資料都是關(guān)于如何使用CoreData存儲數(shù)據(jù)的得糜,即便我們在前面加上Istruments,查到的資料還是關(guān)于如何存儲數(shù)據(jù)的晰洒,還好我們另一位同事找到了資料朝抖。
Core data也叫檢測核心數(shù)據(jù)故障的儀器,主要是用于監(jiān)測讀取谍珊、緩存未命中治宣、保存等操作,能直觀顯示是否保存次數(shù)遠超實際需要。以下的instruments工具收集的數(shù)據(jù)和Core Data應(yīng)用的事件相關(guān)侮邀。你可以使用這些instruments工具返回的信息來評估各種事件對應(yīng)用性能的影響和來定位潛在問題并修復它坏怪。
Core data instrument工具可以運行在單一進程或所有系統(tǒng)當前運行的進程之上。它只會記錄使用Core Data的進程的數(shù)據(jù)绊茧。該instrument工具在實現(xiàn)上使用了DTrace铝宵,并可以導入DTrace腳本。?
Core?Data Fetches 工具記錄Core Data應(yīng)用中提取保存數(shù)據(jù)的操作华畏。
Core?Data Cache Misses?工具記錄高速緩存未命中導致的故障事件鹏秋。
Core?Data Saves 工具記錄了Core?Data應(yīng)用中保存的操作。
8亡笑、Counters ?計數(shù)器 ? ?
從用戶管理的點事件計數(shù)器儀器記錄信息侣夷。它可以記錄從一個過程或系統(tǒng)上運行的所有進程的信息。
9仑乌、Energy Diagnostic ?能量診斷 ??
用于Xcode下的Instruments來分析手機電量消耗的百拓。(必須是真機才有電量)
10、File Activity? 文件活動??
按照介紹this template monitors file and directory activity ,including file open close calls,file permission modifications, directory creation ,file moves ,etc.翻譯過來是:這個模板活動監(jiān)視器文件和目錄,包括文件打開或者關(guān)閉晰甚,文件權(quán)限修改耐版,目錄創(chuàng)建,文件移動等压汪。
11粪牲、GPU Driver 顯卡驅(qū)動程序?
GPU Driver可以測量GPU的利用率,同樣也是一個很好的來判斷和GPU相關(guān)動畫性能的指示器止剖。它同樣也提供了類似Core Animtaion那樣顯示FPS的工具腺阳。
看來這個GPU Driver 還是和Core Animation有關(guān)。
12穿香、Leaks 泄漏 ?
(Mひ!又一個重頭戲來了Fせ瘛1候尽)
首先我們看一看內(nèi)存溢出和內(nèi)存泄漏的區(qū)別。
內(nèi)存溢出 out of memory洒宝,是指程序在申請內(nèi)存時购公,沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory雁歌;比如申請了一個integer,但給它存了long才能存下的數(shù)宏浩,那就是內(nèi)存溢出。
內(nèi)存泄露 memory leak靠瞎,是指程序在申請內(nèi)存后比庄,無法釋放已申請的內(nèi)存空間求妹,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴重佳窑,無論多少內(nèi)存,遲早會被占光制恍。
memory leak會最終會導致out of memory!
在前面的ALLcations里面我們提到過內(nèi)存泄漏就是應(yīng)該釋放而沒有釋放的內(nèi)存神凑。而內(nèi)存泄漏分為兩種:Leaked Memory 和Abandoned Memory净神。前面我們講到了如何找到Abandoned Memory被遺忘的內(nèi)存,現(xiàn)在我們研究的就是Leaked Memory耙厚。
以發(fā)生的方式來分類强挫,內(nèi)存泄漏可以分為4類:
常發(fā)性內(nèi)存泄漏岔霸。發(fā)生內(nèi)存泄漏的代碼會被多次執(zhí)行到薛躬,每次被執(zhí)行的時候都會導致一塊內(nèi)存泄漏。
偶發(fā)性內(nèi)存泄漏呆细。發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會發(fā)生型宝。常發(fā)性和偶發(fā)性是相對的。對于特定的環(huán)境絮爷,偶發(fā)性的也許就變成了常發(fā)性的趴酣。所以測試環(huán)境和測試方法對檢測內(nèi)存泄漏至關(guān)重要。
一次性內(nèi)存泄漏坑夯。發(fā)生內(nèi)存泄漏的代碼只會被執(zhí)行一次岖寞,或者由于算法上的缺陷,導致總會有一塊僅且一塊內(nèi)存發(fā)生泄漏柜蜈。比如仗谆,在類的構(gòu)造函數(shù)中分配內(nèi)存,在析構(gòu)函數(shù)中卻沒有釋放該內(nèi)存淑履,所以內(nèi)存泄漏只會發(fā)生一次隶垮。
隱式內(nèi)存泄漏。程序在運行過程中不停的分配內(nèi)存秘噪,但是直到結(jié)束的時候才釋放內(nèi)存狸吞。嚴格的說這里并沒有發(fā)生內(nèi)存泄漏,因為最終程序釋放了所有申請的內(nèi)存指煎。但是對于一個服務(wù)器程序蹋偏,需要運行幾天,幾周甚至幾個月至壤,不及時釋放內(nèi)存也可能導致最終耗盡系統(tǒng)的所有內(nèi)存暖侨。所以,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏崇渗。
影響:從用戶使用程序的角度來看字逗,內(nèi)存泄漏本身不會產(chǎn)生什么危害京郑,作為一般的用戶,根本感覺不到內(nèi)存泄漏的存在葫掉。真正有危害的是內(nèi)存泄漏的堆積些举,這會最終消耗盡系統(tǒng)所有的內(nèi)存。從這個角度來說俭厚,一次性內(nèi)存泄漏并沒有什么危害户魏,因為它不會堆積,而隱式內(nèi)存泄漏危害性則非常大挪挤,因為較之于常發(fā)性和偶發(fā)性內(nèi)存泄漏它更難被檢測到叼丑。
下邊我們介紹Instruments里面的Leaked的用法,首先打開Leaked扛门,跑起工程來鸠信,點擊要測試的頁面,如果有內(nèi)存泄漏论寨,會出現(xiàn)下圖中的紅色的?星立。然后按照后邊的步驟進行修復即可。
下圖是對Leaked頁面進一步的理解:
當然了葬凳,關(guān)于內(nèi)存泄漏我們還可以用?command +shift +B?的方式進行檢測绰垂,這個快捷鍵調(diào)起的是內(nèi)存管理器Analyze。
也可以從Product里面直接打開
關(guān)于內(nèi)存管理器Analyze解決問題可以參考這篇文章APP Analyze(靜態(tài)分析)也可以參考Analyze問題解決火焰。
使用內(nèi)存管理器遇到的問題大概分為:
1劲装、garbage value(垃圾值)
2、never read(分配了空閑內(nèi)存)
3昌简、Null passed to a callee that requires a non-null 1st parameter(Null賦值給非空對象)
4占业、Potential leak of an object stored into 'XX'(存在潛在的內(nèi)存泄露)
上述兩篇文章很好的解答了出線這4個問題如何解決,這里就不贅述了江场。
關(guān)于內(nèi)存泄露還是比較重要的纺酸,大家看看,測試一下自己項目里面的內(nèi)存泄漏址否,另外如果大家有什么更好的方法餐蔬,希望能夠告訴我,謝謝佑附。
使用上述兩種方法(1)Instruments-Leaked (2)內(nèi)存管理器Analyze ?來檢查內(nèi)存泄漏樊诺,是我們最常用的兩種。
13音同、Metal System Trace??
金屬系統(tǒng)跟蹤??
翻譯下圖紅框的英文得到:金屬ios系統(tǒng)跟蹤配置文件的性能應(yīng)用程序從應(yīng)用程序通過提供跟蹤信息,司機和GPU層词爬。(狗屁不通)從網(wǎng)上找Metal System Trace相關(guān)的資料也沒有找到。誰知道這是干啥用的权均。
14顿膨、Network 網(wǎng)絡(luò)??
同樣是翻譯下邊的英文:分析應(yīng)用程序如何使用TCP / IP和UDP / IP連接使用連接儀器锅锨。就是檢查手機網(wǎng)速的。(這個最好是真機)
15恋沃、OpenGL ES Analysis? openGL分析??
同樣是翻譯下邊的英文:這個模板的措施和分析OpenGL ES活動檢測OpenGL ES正確性和性能問題也提供了解決這些問題的建議必搞。
16、System Trace? 系統(tǒng)跟蹤??
該模板提供了系統(tǒng)行為的全面信息囊咏。它顯示線程何時調(diào)度恕洲,并顯示從用戶到系統(tǒng)代碼的線程轉(zhuǎn)換,通過系統(tǒng)調(diào)用和內(nèi)存操作梅割。這個模板可以在OS X操作系統(tǒng)和iOS上使用霜第。包含三個模板
Scheduling ?Instrument------調(diào)度工具
System Calls ?Instrument---系統(tǒng)調(diào)用儀器
VM Tracker ??Instrument-----VM跟蹤儀
17、System Usage? 系統(tǒng)使用???
這個模板監(jiān)視一個應(yīng)用程序和記錄系統(tǒng)的I / O活動相關(guān)的文件户辞,套接字和共享內(nèi)存泌类。這包括輸入,輸出咆课,時間回溯末誓,調(diào)用樹扯俱,乃至每一次響應(yīng)书蚪。該模板只可用于iOS。包含一個模板
I/O Activity ? ?Instrument-----I/O活動儀
I/O Activity instrument工具記錄I/O事件:函數(shù)調(diào)用迅栅,比如在文件系統(tǒng)上面的read殊校、write、open读存、close等操作为流。你可以使用該instrument工具來啟動和樣本分析單個運行在iOS設(shè)備上面的進程。盡管I/O Activity instrument工具提供了一個調(diào)用樹的回溯跟蹤視圖让簿,在Mac ?OS X上有類似I/O Activity instrument工具的fs_usage實用工具敬察。
18、Time Profiler ?時間分析器?
(又一個重頭戲6薄A觥!)
用來檢測app中每個方法所用的時間椭迎,并且可以排序锐帜,并查找出哪些函數(shù)占用了大量時間。頁面如下:
使用Time Profile前有兩點需要注意的地方:
1畜号、一定要使用真機調(diào)試
在開始進行應(yīng)用程序性能分析的時候缴阎,一定要使用真機。因為模擬器運行在Mac上简软,然而Mac上的CPU往往比iOS設(shè)備要快蛮拔。相反述暂,Mac上的GPU和iOS設(shè)備的完全不一樣二打,模擬器不得已要在軟件層面(CPU)模擬設(shè)備的GPU疾忍,這意味著GPU相關(guān)的操作在模擬器上運行的更慢,尤其是使用CAEAGLLayer來寫一些OpenGL的代碼時候雏逾,這就導致模擬器性能數(shù)據(jù)和用戶真機使用性能數(shù)據(jù)相去甚遠
2踱卵、應(yīng)用程序一定要使用發(fā)布配置
在發(fā)布環(huán)境打包的時候廊驼,編譯器會引入一系列提高性能的優(yōu)化,例如去掉調(diào)試符號或者移除并重新組織代碼惋砂。另iOS引入一種"Watch Dog"[看門狗]機制妒挎,不同的場景下,“看門狗”會監(jiān)測應(yīng)用的性能西饵,如果超出了該場景所規(guī)定的運行時間酝掩,“看門狗”就會強制終結(jié)這個應(yīng)用的進程。開發(fā)者可以crashlog看到對應(yīng)的日志眷柔,但Xcode在調(diào)試配置下會禁用"Watch Dog"
下面解釋了每一個選項對左側(cè)列表中數(shù)據(jù)的顯示起了什么作用:
Separate by Thread:每個線程被單獨考慮期虾。這能讓你知道哪一個線程占用CPU最多。
Invert Call Tree:選中該選項后驯嘱,調(diào)用棧會自上至下顯示镶苞。這通常是你需要的,因為你想知道CPU花費時間的那個最深的方法鞠评。
Hide System Libraries:選中該選項后茂蚓,只有你自己app中出現(xiàn)的符號會被顯示出來。通常選中該選項是有用的剃幌,因為你只關(guān)心CPU在你自己的代碼中的哪一部分花費時間聋涨,你沒法對系統(tǒng)庫使用CPU做多少改變。
Flatten Recursion:該選項將每一個調(diào)用棧中的遞歸函數(shù)(調(diào)用它們自身的函數(shù))視作單一入口负乡,而不是多入口牍白。
Top Functions:選上這一選項讓Instruments將花費在一個函數(shù)中的總時間視作在該函數(shù)中直接花費的時間加上調(diào)用的其他函數(shù)花費的時間。所以如果函數(shù)A調(diào)用了函數(shù)B抖棘,那么函數(shù)A花費的總時間被記為A花費的時間加上B花費的時間茂腥。這一選項非常有用,因為它能讓你在每次進入調(diào)用棧時找到花費最長的時間钉答,瞄準你最耗時的方法础芍。
看到網(wǎng)上有人說主線程耗時過多進行優(yōu)化的,有的是網(wǎng)絡(luò)請求耗時過多進行優(yōu)化的数尿,有的是UIImage耗時過多進行優(yōu)化的仑性,總之,可以看到哪個函數(shù)耗時多右蹦,進而優(yōu)化诊杆,在這里不由得想起了本文開頭提到的一位網(wǎng)友說的:Instruments的價值在于歼捐,它使我們深刻理解我們代碼的內(nèi)部運作。誠不欺吾晨汹。
總結(jié):性能優(yōu)化是在所有更能實現(xiàn)完成時要做的事豹储,使用Time Profile工具分析app每個流程的執(zhí)行情況,發(fā)現(xiàn)耗時的地方淘这,合理優(yōu)化剥扣,提升用戶體驗,切記铝穷,優(yōu)化后要做一遍詳細的測試钠怯,別修了東墻壞了西墻。
19曙聂、Zombies ?僵尸 ?
(最后一個晦炊,也是最后一個重頭戲)
翻譯英文:專注于檢測過度釋放的“僵尸”對象。還提供了數(shù)據(jù)對象分配的類以及所有活動分配內(nèi)存地址的歷史宁脊。
這里我們可以看到一個詞語叫“over-release”,過度釋放断国。我們在項目中見到最多的就是“EXC_BAD_ACCESS”或者是這樣的:Thread 1: Program received signal:"EXC_BAD_ACCESS",這就是訪問了被釋放的內(nèi)存地址造成的榆苞。過度釋放稳衬,是對同一個對象釋放了過多的次數(shù),其實當引用計數(shù)降到0時语稠,對象占用的內(nèi)存已經(jīng)被釋放掉宋彼,此時指向原對象的指針就成了“懸垂指針”弄砍,如若再對其進行任何方法的調(diào)用仙畦,(原則上)都會直接crash(然而由于某些特殊的情況,不會馬上crash)音婶。過度釋放簡單的說就是對release的對象再release慨畸,就是過度釋放。
我們需要知道這幾個概念:
1衣式、內(nèi)存泄漏:對象使用完沒有釋放寸士,導致內(nèi)存浪費。
2碴卧、僵尸對象:已經(jīng)被銷毀的對象(不能再使用的對象)
3弱卡、野指針:指向僵尸對象(不可用內(nèi)存)的指針。給野指針發(fā)消息會報EXC_BAD_ACCECC錯誤住册。
4婶博、空指針:沒有指向儲存空間的指針(里面存的是nil,也就是0)。在oc中使用空指針調(diào)中方法不會報錯荧飞。
注意:為了避免野指針錯誤的常見方法:在對象被銷毀之后,將指向?qū)ο蟮闹羔樧優(yōu)榭罩羔槨?/p>
對于過度釋放的問題凡人,可以直接使用Zombie名党,當過度釋放發(fā)生時會立即停在發(fā)生問題的位置,同時結(jié)合內(nèi)存分配釋放歷史和調(diào)用棧挠轴,可以發(fā)現(xiàn)問題传睹。至于上文提到的不會crash的原因,其實有很多岸晦,比如:
對象內(nèi)存釋放時欧啤,所用內(nèi)存并沒有完全被擦除,仍有舊對象部分數(shù)據(jù)可用
原內(nèi)存位置被寫入同類或同樣結(jié)構(gòu)的數(shù)據(jù)
我們將僵尸對象“復活”的目的:僵尸對象就是讓已經(jīng)釋放了的對象重新復活启上,便于調(diào)試堂油;是為了讓已經(jīng)釋放了的對象在被再次訪問時能夠輸出一些錯誤信息。其實這里的“復活”并不是真的復活碧绞,而是強行不死:這么說吧 相當于 他的RC=0的時候 系統(tǒng)再強行讓他RC=1府框,順便打上一個標記 zoom,等到你去掉那個溝以后 系統(tǒng)會把帶有標記zoom的對象RC=0讥邻。
可以參考IOS性能調(diào)優(yōu)系列:使用Zombies動態(tài)分析內(nèi)存中的僵尸對象
可以參考ios 調(diào)試技巧收藏 一 解決EXC_BAD_ACCESS錯誤的一種方法--NSZombieEnabled
可以參考野指針與僵尸對象
下邊是Instruments里面的Zombies的用法:
接下來進行設(shè)置,在Launch ?Configuration中勾選Record reference counts和Enable NSZombie?detection迫靖。其中Recordreference counts是顯示引用計數(shù),Enable?NSZombie detection是能夠檢測僵尸對象兴使。
這樣在程序運行的時候系宜,如果發(fā)現(xiàn)僵尸對象它就會彈出一個對話框,點擊其中“→”按鈕发魄,在屏幕的下方會顯示僵尸對象的詳細信息盹牧,下圖可以看到僵尸對象的引用計數(shù)變化情況。
注意:Zombies模版在使用的時候會導致內(nèi)存的飆升励幼,這是因為所有被釋放的對象被僵尸對象取代汰寓,并未真的釋放掉,在結(jié)束Zombies時會釋放苹粟,這是預知行為有滑,這就意味著instrument里的其它工具和Zombies是不能同時使用的,Zombies會導致其它的數(shù)據(jù)不準嵌削。包括leaks毛好,你也不應(yīng)該把它加到Zombies模版中,即使這么做了結(jié)果也沒什么意義苛秕。對于iOS應(yīng)用來說肌访,在用Zombies模版時使用iOS模擬器比真機要好。
另外XCode也提供了手動設(shè)置NSZombieEnabled環(huán)境變量的方法艇劫,不過設(shè)置NSZombieEnabled為True后吼驶,會導致內(nèi)存占用的增長,同時會影響Leaks工具的調(diào)試,這是因為設(shè)置NSZombieEnabled會用僵尸對象來代替已釋放對象旨剥。
點擊Product菜單Edit?Scheme打開該頁面咧欣,然后勾選Enable Zombie Objects復選框:
最后提醒的是NSZombieEnabled只能在調(diào)試的時候使用,千萬不要忘記在產(chǎn)品發(fā)布的時候去掉轨帜,因為NSZombieEnabled不會真正去釋放dealloc對象的內(nèi)存魄咕,一直開啟的話,該死去的對象會一直存在蚌父,后果可想而知哮兰,自重!
好了苟弛,結(jié)束了喝滞。還是那句話:Instruments的價值在于,它使我們深刻理解我們代碼的內(nèi)部運作膏秫。
最后右遭,哪里不對的地方可以給我留言,我會及時改進的缤削,謝謝大家窘哈。