更新于:20170814
更新于:20171222
再次更新于:20180823
最近的幾天在看一些 Instruments 相關(guān)的知識,總結(jié)分享一下希望對大家有所幫助:
本文章主要介紹的是 Instruments 的相關(guān)知識,以及如何使用 Instruments的 Leaks 工具晨炕。 Instruments 其它的工具會在后面篇文章一一介紹.
前言介紹:
或許很多朋友對 Instruments 應(yīng)用不太了解棒旗,但可能很多老的 iOS 開發(fā)者都應(yīng)該用過 Instruments 工具來檢測 iOS 應(yīng)用內(nèi)存泄漏情況侧但。特別是在 iOS 5.0 之前,即蘋果在iOS 平臺上面還沒支持 ARC 的時候更米,寫 iOS 應(yīng)用就類似 C 語言那樣,容易忘記釋放內(nèi)存毫痕,而內(nèi)存對移動設(shè)備而言是非痴髀停可貴的迟几。即使目前 iPhone 設(shè)備內(nèi)存已經(jīng)滿足 512MB 了,但是因?yàn)樘O果的后臺模式是把整個應(yīng)用封裝起來等待下次啟用栏笆,所以該應(yīng)用所占用的內(nèi)存同樣被占據(jù)了类腮。也就是即使應(yīng)用進(jìn)入后臺模式,它還是仍然占用原先的內(nèi)存的蛉加,所以你打開的應(yīng)用越多蚜枢,內(nèi)存耗用自然也很多。對很多普通用戶而言针饥,往往他們打開的應(yīng)用都是進(jìn)入后臺模式的厂抽,很少有用戶清理后臺的應(yīng)用,所以也就造成很多應(yīng)用其實(shí)可用內(nèi)存還是非常有限地 (題外話:如果蘋果原生支持一鍵清理后臺程序就好了打厘,貌似越獄的工具里面有這樣的支持的岖沛。
還有做過 iOS 應(yīng)用自動化測試的開發(fā)者磅网,應(yīng)該對UIAutomation 很熟悉吧蔼卡。它就是通過 JS 腳本來寫界面自動化測試用例违帆。而 Instruments 應(yīng)用對 UIAutomation 支持很完善,你可以通過它查看很多代碼潛在的問題莽鸭,并測試性能吗伤。
其實(shí) Instruments 應(yīng)用還有很多強(qiáng)大的功能,它原生支持很多 instrument 工具硫眨,幫助你分析你的代碼足淆,不僅包括內(nèi)存檢測和自動化測試,它還可以監(jiān)測文件讀寫操作等等礁阁。所以一個好的 iOS 開發(fā)者是應(yīng)該掌握 Instrument 應(yīng)用的使用巧号。因?yàn)?Instruments 應(yīng)用本身功能太強(qiáng)大的,所以完全掌握機(jī)會不可能姥闭,但是因?yàn)樗鼈儍?nèi)置的很多工具具有相似性丹鸿,所以基本掌握自己常用的即可。同時了解一下內(nèi)部有哪些功能棚品,這樣在你需要用到的時候再查查文檔靠欢,就可以很快上手了。
正文 Instruments 的介紹:
- Instruments 是一個很靈活的铜跑、強(qiáng)大的工具门怪;是性能分析、動態(tài)跟蹤 和分析 OS X 以及 iOS 代碼的測試工具锅纺;用它可以極為方便收集關(guān)于一個或多個系統(tǒng)進(jìn)程的性能和行為的數(shù)據(jù)掷空,并能及時隨著時間跟蹤而產(chǎn)生的數(shù)據(jù),并檢查所收集的數(shù)據(jù),還可以廣泛收集不同類型的數(shù)據(jù)拣帽;也可以追蹤程序運(yùn)行的過程疼电,這樣 instrument 就可以幫助我們了解用戶的應(yīng)用程序和操作系統(tǒng)的行為。
總結(jié)一下 instrument 能做的事情:
1.Instruments 是用于動態(tài)調(diào)追蹤和分析 OS X 和 iOS 的代碼的性能分析和測試工具减拭;
2.Instruments 支持多線程的調(diào)試;
3.可以用 Instruments 去錄制和回放区丑,圖形用戶界面的操作過程
4.可將錄制的圖形界面操作和 Instruments 保存為模板拧粪,供以后訪問使用。
或者說:
1.追蹤代碼中的(甚至是那些難以復(fù)制的)問題沧侥;
2.分析程序的性能可霎;
3.實(shí)現(xiàn)程序的自動化測試;
4.部分實(shí)現(xiàn)程序的壓力測試宴杀;
5.執(zhí)行系統(tǒng)級別的通用問題追蹤調(diào)試癣朗;
6.使你對程序的內(nèi)部運(yùn)行過程更加了解。
介紹幾個常用的 instrument 工具:
- Leaks(泄漏):一般的查看內(nèi)存使用情況旺罢,檢查泄漏的內(nèi)存旷余,并提供了所有活動的分配和泄漏模塊的類對象分配統(tǒng)計信息以及內(nèi)存地址歷史記錄;
- Time Profiler(時間探查):執(zhí)行對系統(tǒng)的 CPU上運(yùn)行的進(jìn)程低負(fù)載時間為基礎(chǔ)采樣扁达。
- Allocations(內(nèi)存分配):跟蹤過程的匿名虛擬內(nèi)存和堆的對象提供類名和可選保留/釋放歷史正卧;
- Activity Monitor(活動監(jiān)視器):顯示器處理的 CPU、內(nèi)存和網(wǎng)絡(luò)使用情況統(tǒng)計跪解;
- Blank(空模板):創(chuàng)建一個空的模板炉旷,可以從 Library 庫中添加其他模板;
- Automation(自動化):這個模板執(zhí)行它模擬用戶界面交互為 iOS 手機(jī)應(yīng)用從 instrument 啟動的腳本叉讥;
- Core Data:監(jiān)測讀取窘行、緩存未命中、保存等操作图仓,能直觀顯示是否保存次數(shù)遠(yuǎn)超實(shí)際需要罐盔。
- Cocoa Layout:觀察約束變化,找出布局代碼的問題所在透绩。
- Network:跟蹤 TCP/IP 和 UDP/IP 連接翘骂。
- Automations:創(chuàng)建和編輯測試腳本來自動化 iOS 應(yīng)用的用戶界面測試。
Instruments 常用的三大類:
- Leaks:找到引發(fā)內(nèi)存泄漏的起點(diǎn)
- Time Profiler:分析代碼的執(zhí)行時間帚豪,找出導(dǎo)致程序變慢的原因
- Allocations:監(jiān)測內(nèi)存使用/分配情況
一碳竟、使用 Instruments 的 Leaks工具
[??nstr?m(?)nt] [liks 漏洞]
迅速膨脹的內(nèi)存可以很快讓程序斃命,所以要多加防范狸臣。即使有 ARC(自動引用計數(shù))內(nèi)存管理機(jī)制莹桅,但在現(xiàn)實(shí)中對象之間引用復(fù)雜,循環(huán)引用導(dǎo)致的內(nèi)存泄漏仍然難以避免,所以關(guān)鍵時刻還要自力更生诈泼。分析內(nèi)存泄露不能把所有的內(nèi)存泄露查出來懂拾,有的內(nèi)存泄露是在運(yùn)行時,用戶操作時才產(chǎn)生的铐达。那就需要用到 Instruments 的leaks 了岖赋。
- Leaks 調(diào)試解決 iOS 內(nèi)存泄漏的工具 快捷鍵:command + control + i
打開步驟:
- 首先我們選中 Xcode先把模擬器(command + R)運(yùn)行起來
- 然后我們再選中 Xcode,按快捷鍵(command + control + i)運(yùn)行起來, 選擇 Leaks --> Choose
沒有明顯變化瓮孙,如果這些工具不夠可以自行添加
或者 點(diǎn)擊 Xcode 的 “調(diào)試導(dǎo)航”
然后選中 “Memory”唐断,再點(diǎn)擊右側(cè)的 “Profile in Instruments”,
會自動打開 Instruments杭抠。這時候會彈出來一個對話框脸甘,
選擇 “Transfer” 這種方式打開
在或者你可以通過 Xcode --> Open Developer Tool --> instruments --> Leaks 的方式來打開
再或者你可以 按著 control+空格鍵,輸入instruments 打開 (meishichulaihaha)
打開后偏灿,這時界面如圖 <老版本的>:
- 由于 Leaks 是動態(tài)監(jiān)測丹诀,所以我們需要手動操作 APP,進(jìn)行測試翁垂,一邊操作 APP铆遭,一邊觀察 Leaks 的變化,在
暫停按鈕
的右邊 我們可以選擇正在 運(yùn)行的程序 & 選擇設(shè)備 & App, 之后點(diǎn)擊 紅點(diǎn) Record(紅色圓圈按鈕)運(yùn)行沮峡。 - 觀察疚脐,如果發(fā)現(xiàn)在 Leaks 里面有一個 紅色X,這說明了我們的 APP 存在內(nèi)存泄露邢疙。
- 點(diǎn)擊暫停棍弄,點(diǎn)擊其中一個疟游,然后我們開始分析呼畸。(也可繼續(xù)檢測,當(dāng)多個時暫停颁虐,一次處理了多個)
-
下面就是定位修改了, 此時選中有紅色叉的 Leaks蛮原,下面有個
田
Leaks 字方格,點(diǎn)開另绩,選中 Call Tree儒陨。
-
接著就是最關(guān)鍵的一步,在這個界面的右下角有若干選框笋籽,選中Invert Call Tree 和 Hide System Libraries,(紅圈范圍內(nèi))如果不知道在那個位置請接著往下看
定位
在詳情面板選中顯示的若干條中的一條蹦漠,雙擊,會自動跳到內(nèi)存泄露代碼處车海,然后點(diǎn)擊右上角 Xcode 圖標(biāo)進(jìn)行修改笛园。
Leaks界面講解:
Leaks 啟動后會開始錄制,隨著對模擬器運(yùn)行的 App 的操作,可以在 Leaks 中查看內(nèi)存占用的情況研铆。
Leaks頂部分為兩欄:Allocations (al??ke??(?)n,分配 ) 和 Leaks埋同,右側(cè)的曲線代表內(nèi)存分配和內(nèi)存泄漏曲線。
-
點(diǎn)擊第二欄 Leaks棵红,如下圖:
-
進(jìn)行內(nèi)存泄漏分析凶赁,右下角會出現(xiàn)Leaks調(diào)試的選項(xiàng):
1、Record Settings (?r?k??d 記錄設(shè)置)
2窄赋、Display Settings 選項(xiàng)面板
3哟冬、Extended Detail 擴(kuò)展面板(?k?st?nd,延展 di?te?l,細(xì)節(jié)詳情),在時間探查儀器的情況下忆绰,它是用來跟蹤顯示堆棧。
老版本是在右邊顯示:
現(xiàn)在已經(jīng)改為:
之前說過可岂,新本版做了改變错敢,需要先選擇 Call Tree
內(nèi)存泄漏動態(tài)分析技巧:
- 1.在 Display Settings 界面建議把 Snapshot Interval (snap??t, 數(shù)據(jù)快照)間隔時間設(shè)置為10秒,勾選Automatic Snapshotting缕粹,Leaks 會自動進(jìn)行內(nèi)存捕捉分析稚茅。(新版本直接在底部修改)
- 2.熟練使用 Leaks 后會對內(nèi)存泄漏判斷更準(zhǔn)確,在可能導(dǎo)致泄漏的操作里平斩,在你懷疑有內(nèi)存泄漏的操作前和操作后亚享,可以點(diǎn)擊 Snapshot Now 進(jìn)行手動捕捉。
- 3.開始時如果設(shè)備性能較好绘面,可以把自動捕捉間隔設(shè)置為 5 秒鐘欺税。
- 4.使用ARC的項(xiàng)目,一般內(nèi)存泄漏都是 malloc揭璃、自定義結(jié)構(gòu)晚凿、資源引起的,多注意這些地方進(jìn)行分析瘦馍。
- 5.開啟ARC后歼秽,內(nèi)存泄漏的原因
開啟了ARC并不是就不會存在內(nèi)存問題,蘋果有句名言:ARC is only for NSObject情组。 - 注:如果你的項(xiàng)目使用了ARC燥筷,隨著你的操作,不斷開啟或關(guān)閉視圖院崇,內(nèi)存可能持續(xù)上升肆氓,但這不一定表示存在內(nèi)存泄漏,ARC釋放的時機(jī)是不固定的亚脆。
做一下就簡單的演示:
- 項(xiàng)目:
創(chuàng)建 single View App
添加一個People 類
- 這里選用的是MRC :
- 在 Main.storyboard 里拖了一個 button 并且為 button的 “touchUpInset”事件綁定 buttonClick:事件處理方法
- 在 People.h 文件里面代碼如下
#import <Foundation/Foundation.h>
@interface People : NSObject
@property (nonatomic, assign) NSString *str;
@end
- 在 UIViewController.m 文件里面代碼如下:
- (IBAction)buttonClick:(id)sender {
People * people = [[People alloc]init];
[people retain];
people.str = @"1324567";
}
- 運(yùn)行項(xiàng)目做院,切換到 iOS 模擬器,點(diǎn)擊那個測試按鈕多點(diǎn)幾次 “button”,
- 切換到 Instruments 會發(fā)現(xiàn) 如果沒有泄漏 如圖
- 當(dāng)然這里是泄漏键耕,在 “Leaks” 一欄里有紅色的 X寺滚。如圖這就是內(nèi)存泄露了。
點(diǎn)擊暫停屈雄,然后點(diǎn)擊 “Leaks” 一欄
-
然后點(diǎn)擊“導(dǎo)航欄”切換到“call tree”模式下
-
看到列表里列出了內(nèi)存泄露的調(diào)用邏輯:
注意:
在老版本中:
- 需要勾選右邊的詳細(xì)窗口 Display Settings 中的 Call Tree 中 Separate by Thread 和 Hide System Libraries 兩個選項(xiàng),
Hide System Libraries 作用是隱藏系統(tǒng)函數(shù)村视。如果不點(diǎn)擊 這里顯示的是執(zhí)行代碼完整路徑,其中系統(tǒng)和應(yīng)用本身一些調(diào)用路徑完全揉捏在一起. 完全看不到我們關(guān)心的應(yīng)用程序中實(shí)際代碼執(zhí)行耗時和代碼路徑實(shí)際所在位置
不勾選效果如下:
勾選效果如下:
在新的版本中 Call Tree 的 這些設(shè)置換了位置 在底部左下角:
-
勾選之后酒奶,雙擊一下就會來到內(nèi)存泄漏的地方
這里對 Display Settings 中 的 Call tree
選項(xiàng)做一下說明 [官方user guide翻譯]:
Separate By Thread: 線程分離,只有這樣才能在調(diào)用路徑中能夠清晰看到占用CPU最大的線程.每個線程應(yīng)該分開考慮蚁孔。只有這樣你才能揪出那些大量占用CPU的"重"線程,按線程分開做分析惋嚎,這樣更容易揪出那些吃資源的問題線程杠氢。特別是對于主線程,它要處理和渲染所有的接口數(shù)據(jù)另伍,一旦受到阻塞鼻百,程序必然卡頓或停止響應(yīng)。
Invert Call Tree: 從上到下跟蹤堆棧信息.這個選項(xiàng)可以快捷的看到方法調(diào)用路徑最深方法占用CPU耗時(這意味著你看到的表中的方法,將已從第0幀開始取樣,這通常你是想要的,只有這樣你才能看到CPU中話費(fèi)時間最深的方法),比如FuncA{FunB{FunC}},勾選后堆棧以C->B->A把調(diào)用層級最深的C顯示最外面.反向輸出調(diào)用樹摆尝。把調(diào)用層級最深的方法顯示在最上面温艇,更容易找到最耗時的操作。
Hide Missing Symbols:如果dSYM無法找到你的APP或者調(diào)用系統(tǒng)框架的話堕汞,那么表中將看到調(diào)用方法名只能看到16進(jìn)制的數(shù)值,勾選這個選項(xiàng)則可以隱藏這些符號勺爱,便于簡化分析數(shù)據(jù).
Hide System Libraries: 表示隱藏系統(tǒng)的函數(shù),調(diào)用這個就更有用了,勾選后耗時調(diào)用路徑只會顯示app耗時的代碼,性能分析普遍我們都比較關(guān)系自己代碼的耗時而不是系統(tǒng)的.基本是必選項(xiàng).注意有些代碼耗時也會納入系統(tǒng)層級讯检,可以進(jìn)行勾選前后前后對執(zhí)行路徑進(jìn)行比對會非常有用.因?yàn)橥ǔD阒魂P(guān)心cpu花在自己代碼上的時間不是系統(tǒng)上的琐鲁,隱藏系統(tǒng)庫文件。過濾掉各種系統(tǒng)調(diào)用视哑,只顯示自己的代碼調(diào)用绣否。隱藏缺失符號。如果 dSYM 文件或其他系統(tǒng)架構(gòu)缺失挡毅,列表中會出現(xiàn)很多奇怪的十六進(jìn)制的數(shù)值蒜撮,用此選項(xiàng)把這些干擾元素屏蔽掉,讓列表回歸清爽跪呈。
Show Obj-C Only: 只顯示oc代碼 ,如果你的程序是像OpenGl這樣的程序,不要勾選側(cè)向因?yàn)樗锌赡苁荂++的
Flatten Recursion: 遞歸函數(shù), 每個堆棧跟蹤一個條目段磨,拼合遞歸。將同一遞歸函數(shù)產(chǎn)生的多條堆棧(因?yàn)檫f歸函數(shù)會調(diào)用自己)合并為一條耗绿。
Top Functions: 找到最耗時的函數(shù)或方法苹支。 一個函數(shù)花費(fèi)的時間直接在該函數(shù)中的總和,以及在函數(shù)調(diào)用該函數(shù)所花費(fèi)的時間的總時間误阻。因此债蜜,如果函數(shù)A調(diào)用B晴埂,那么A的時間報告在A花費(fèi)的時間加上B.花費(fèi)的時間,這非常真有用,因?yàn)樗梢宰屇忝看蜗碌秸{(diào)用堆棧時挑最大的時間數(shù)字寻定,歸零在你最耗時的方法儒洛。
需要添加其他工具的話:
進(jìn)行如下操作:
關(guān)于界面的一些其他的補(bǔ)充:
- 左邊的Show the CPU Data 可以查看每個CPU的消耗情況
- 中間的Show the Instruments Data 顯示整體的消耗情況
- 右邊的Show the Thread Data 可以查看每個線程對CPU的消耗情況
選擇 Detail -> Call Tree
表示查看整個調(diào)用過程有了上面的基礎(chǔ)知識就可以對App的CPU消耗情況進(jìn)行實(shí)時檢測了。
問題分析
首先 由于 Leaks 是動態(tài)監(jiān)測狼速,所以我們需要手動操作 APP琅锻,進(jìn)行測試,一邊操作 APP向胡,一邊觀察 Leaks 的變化恼蓬。
也就是說 兩者必須關(guān)聯(lián)好,最為簡單的方法就是:
問題一
- leaks->Call Tree->Call Tree-> 指針地址界面僵芹,右上角欄目xcode圖標(biāo)是灰色的处硬,不能用?設(shè)置齒輪圖標(biāo)也是灰色的拇派?
-
回復(fù):我自己復(fù)現(xiàn)了一下該情況 正常情況下:
注意我這里是 Run 1 of 1 若果是其它的 Run 1 of 2/3/4... & Run 2/ 3 of 2 就不可以點(diǎn)擊了郁油。
問題二
UIAutomation 在哪里?Instruments 里面沒有攀痊?
回復(fù):目前沒有了,或者使用老的版本 或者使用 UITests