Xcode 8 Instruments 學(xué)習(xí)(一)

更新于:20170814
更新于:20171222
再次更新于:20180823


最近的幾天在看一些 Instruments 相關(guān)的知識(shí),總結(jié)分享一下希望對(duì)大家有所幫助:

本文章主要介紹的是 Instruments 的相關(guān)知識(shí),以及如何使用 Instruments的 Leaks 工具。 Instruments 其它的工具會(huì)在后面篇文章一一介紹.

前言介紹:

或許很多朋友對(duì) Instruments 應(yīng)用不太了解,但可能很多老的 iOS 開發(fā)者都應(yīng)該用過 Instruments 工具來檢測(cè) iOS 應(yīng)用內(nèi)存泄漏情況。特別是在 iOS 5.0 之前,即蘋果在iOS 平臺(tái)上面還沒支持 ARC 的時(shí)候,寫 iOS 應(yīng)用就類似 C 語言那樣,容易忘記釋放內(nèi)存,而內(nèi)存對(duì)移動(dòng)設(shè)備而言是非??少F的。即使目前 iPhone 設(shè)備內(nèi)存已經(jīng)滿足 512MB 了,但是因?yàn)樘O果的后臺(tái)模式是把整個(gè)應(yīng)用封裝起來等待下次啟用,所以該應(yīng)用所占用的內(nèi)存同樣被占據(jù)了。也就是即使應(yīng)用進(jìn)入后臺(tái)模式,它還是仍然占用原先的內(nèi)存的,所以你打開的應(yīng)用越多,內(nèi)存耗用自然也很多。對(duì)很多普通用戶而言,往往他們打開的應(yīng)用都是進(jìn)入后臺(tái)模式的,很少有用戶清理后臺(tái)的應(yīng)用,所以也就造成很多應(yīng)用其實(shí)可用內(nèi)存還是非常有限地 (題外話:如果蘋果原生支持一鍵清理后臺(tái)程序就好了,貌似越獄的工具里面有這樣的支持的。

還有做過 iOS 應(yīng)用自動(dòng)化測(cè)試的開發(fā)者,應(yīng)該對(duì)UIAutomation 很熟悉吧。它就是通過 JS 腳本來寫界面自動(dòng)化測(cè)試用例。而 Instruments 應(yīng)用對(duì) UIAutomation 支持很完善,你可以通過它查看很多代碼潛在的問題,并測(cè)試性能。

其實(shí) Instruments 應(yīng)用還有很多強(qiáng)大的功能,它原生支持很多 instrument 工具,幫助你分析你的代碼,不僅包括內(nèi)存檢測(cè)和自動(dòng)化測(cè)試,它還可以監(jiān)測(cè)文件讀寫操作等等。所以一個(gè)好的 iOS 開發(fā)者是應(yīng)該掌握 Instrument 應(yīng)用的使用。因?yàn)?Instruments 應(yīng)用本身功能太強(qiáng)大的,所以完全掌握機(jī)會(huì)不可能,但是因?yàn)樗鼈儍?nèi)置的很多工具具有相似性,所以基本掌握自己常用的即可。同時(shí)了解一下內(nèi)部有哪些功能,這樣在你需要用到的時(shí)候再查查文檔,就可以很快上手了。

以上段落來源鏈接


正文 Instruments 的介紹:

  • Instruments 是一個(gè)很靈活的、強(qiáng)大的工具;是性能分析、動(dòng)態(tài)跟蹤 和分析 OS X 以及 iOS 代碼的測(cè)試工具;用它可以極為方便收集關(guān)于一個(gè)或多個(gè)系統(tǒng)進(jìn)程的性能和行為的數(shù)據(jù),并能及時(shí)隨著時(shí)間跟蹤而產(chǎn)生的數(shù)據(jù),并檢查所收集的數(shù)據(jù),還可以廣泛收集不同類型的數(shù)據(jù);也可以追蹤程序運(yùn)行的過程,這樣 instrument 就可以幫助我們了解用戶的應(yīng)用程序和操作系統(tǒng)的行為。

總結(jié)一下 instrument 能做的事情:

1.Instruments 是用于動(dòng)態(tài)調(diào)追蹤和分析 OS X 和 iOS 的代碼的性能分析和測(cè)試工具;
2.Instruments 支持多線程的調(diào)試;
3.可以用 Instruments 去錄制和回放,圖形用戶界面的操作過程
4.可將錄制的圖形界面操作和 Instruments 保存為模板,供以后訪問使用。

或者說:

1.追蹤代碼中的(甚至是那些難以復(fù)制的)問題;
2.分析程序的性能;
3.實(shí)現(xiàn)程序的自動(dòng)化測(cè)試;
4.部分實(shí)現(xiàn)程序的壓力測(cè)試;
5.執(zhí)行系統(tǒng)級(jí)別的通用問題追蹤調(diào)試;
6.使你對(duì)程序的內(nèi)部運(yùn)行過程更加了解。

以上資料鏈接


介紹幾個(gè)常用的 instrument 工具:
  • Leaks(泄漏):一般的查看內(nèi)存使用情況,檢查泄漏的內(nèi)存,并提供了所有活動(dòng)的分配和泄漏模塊的類對(duì)象分配統(tǒng)計(jì)信息以及內(nèi)存地址歷史記錄;
  • Time Profiler(時(shí)間探查):執(zhí)行對(duì)系統(tǒng)的 CPU上運(yùn)行的進(jìn)程低負(fù)載時(shí)間為基礎(chǔ)采樣。
  • Allocations(內(nèi)存分配):跟蹤過程的匿名虛擬內(nèi)存和堆的對(duì)象提供類名和可選保留/釋放歷史;
  • Activity Monitor(活動(dòng)監(jiān)視器):顯示器處理的 CPU、內(nèi)存和網(wǎng)絡(luò)使用情況統(tǒng)計(jì);
  • Blank(空模板):創(chuàng)建一個(gè)空的模板,可以從 Library 庫中添加其他模板;
  • Automation(自動(dòng)化):這個(gè)模板執(zhí)行它模擬用戶界面交互為 iOS 手機(jī)應(yīng)用從 instrument 啟動(dòng)的腳本;
  • Core Data:監(jiān)測(cè)讀取、緩存未命中、保存等操作,能直觀顯示是否保存次數(shù)遠(yuǎn)超實(shí)際需要。
  • Cocoa Layout:觀察約束變化,找出布局代碼的問題所在。
  • Network:跟蹤 TCP/IP 和 UDP/IP 連接。
  • Automations:創(chuàng)建和編輯測(cè)試腳本來自動(dòng)化 iOS 應(yīng)用的用戶界面測(cè)試。

Instruments 常用的三大類:
  • Leaks:找到引發(fā)內(nèi)存泄漏的起點(diǎn)
  • Time Profiler:分析代碼的執(zhí)行時(shí)間,找出導(dǎo)致程序變慢的原因
  • Allocations:監(jiān)測(cè)內(nèi)存使用/分配情況

一、使用 Instruments 的 Leaks工具

[??nstr?m(?)nt] [liks 漏洞]

迅速膨脹的內(nèi)存可以很快讓程序斃命,所以要多加防范。即使有 ARC(自動(dòng)引用計(jì)數(shù))內(nèi)存管理機(jī)制,但在現(xiàn)實(shí)中對(duì)象之間引用復(fù)雜,循環(huán)引用導(dǎo)致的內(nèi)存泄漏仍然難以避免,所以關(guān)鍵時(shí)刻還要自力更生。分析內(nèi)存泄露不能把所有的內(nèi)存泄露查出來,有的內(nèi)存泄露是在運(yùn)行時(shí),用戶操作時(shí)才產(chǎn)生的。那就需要用到 Instruments 的leaks 了。
  • Leaks 調(diào)試解決 iOS 內(nèi)存泄漏的工具 快捷鍵:command + control + i

打開步驟:
    1. 首先我們選中 Xcode先把模擬器(command + R)運(yùn)行起來
    1. 然后我們?cè)龠x中 Xcode,按快捷鍵(command + control + i)運(yùn)行起來, 選擇 Leaks --> Choose
之前的
2018-08-23

沒有明顯變化,如果這些工具不夠可以自行添加



或者 點(diǎn)擊 Xcode 的 “調(diào)試導(dǎo)航”

然后選中 “Memory”,再點(diǎn)擊右側(cè)的 “Profile in Instruments”,

會(huì)自動(dòng)打開 Instruments。這時(shí)候會(huì)彈出來一個(gè)對(duì)話框,

選擇 “Transfer” 這種方式打開

在或者你可以通過 Xcode --> Open Developer Tool --> instruments --> Leaks 的方式來打開

再或者你可以 按著 control+空格鍵,輸入instruments 打開 (meishichulaihaha)

打開后,這時(shí)界面如圖 <老版本的>:

  • 由于 Leaks 是動(dòng)態(tài)監(jiān)測(cè),所以我們需要手動(dòng)操作 APP,進(jìn)行測(cè)試,一邊操作 APP,一邊觀察 Leaks 的變化,在 暫停按鈕 的右邊 我們可以選擇正在 運(yùn)行的程序 & 選擇設(shè)備 & App, 之后點(diǎn)擊 紅點(diǎn) Record(紅色圓圈按鈕)運(yùn)行。
  • 觀察,如果發(fā)現(xiàn)在 Leaks 里面有一個(gè) 紅色X,這說明了我們的 APP 存在內(nèi)存泄露。
  • 點(diǎn)擊暫停,點(diǎn)擊其中一個(gè),然后我們開始分析。(也可繼續(xù)檢測(cè),當(dāng)多個(gè)時(shí)暫停,一次處理了多個(gè))


  • 下面就是定位修改了, 此時(shí)選中有紅色叉的 Leaks,下面有個(gè) Leaks 字方格,點(diǎn)開,選中 Call Tree。

  • 接著就是最關(guān)鍵的一步,在這個(gè)界面的右下角有若干選框,選中Invert Call Tree 和 Hide System Libraries,(紅圈范圍內(nèi))如果不知道在那個(gè)位置請(qǐng)接著往下看

  • 定位
    在詳情面板選中顯示的若干條中的一條,雙擊,會(huì)自動(dòng)跳到內(nèi)存泄露代碼處,然后點(diǎn)擊右上角 Xcode 圖標(biāo)進(jìn)行修改。



Leaks界面講解:
  • Leaks 啟動(dòng)后會(huì)開始錄制,隨著對(duì)模擬器運(yùn)行的 App 的操作,可以在 Leaks 中查看內(nèi)存占用的情況。

  • Leaks頂部分為兩欄:Allocations (al??ke??(?)n,分配 ) 和 Leaks,右側(cè)的曲線代表內(nèi)存分配和內(nèi)存泄漏曲線。

  • 點(diǎn)擊第二欄 Leaks,如下圖:


  • 進(jìn)行內(nèi)存泄漏分析,右下角會(huì)出現(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é)詳情),在時(shí)間探查儀器的情況下,它是用來跟蹤顯示堆棧。

老版本是在右邊顯示:


現(xiàn)在已經(jīng)改為:


之前說過,新本版做了改變,需要先選擇 Call Tree




內(nèi)存泄漏動(dòng)態(tài)分析技巧:
  • 1.在 Display Settings 界面建議把 Snapshot Interval (snap??t, 數(shù)據(jù)快照)間隔時(shí)間設(shè)置為10秒,勾選Automatic Snapshotting,Leaks 會(huì)自動(dòng)進(jìn)行內(nèi)存捕捉分析。(新版本直接在底部修改)
  • 2.熟練使用 Leaks 后會(huì)對(duì)內(nèi)存泄漏判斷更準(zhǔn)確,在可能導(dǎo)致泄漏的操作里,在你懷疑有內(nèi)存泄漏的操作前和操作后,可以點(diǎn)擊 Snapshot Now 進(jìn)行手動(dòng)捕捉。
  • 3.開始時(shí)如果設(shè)備性能較好,可以把自動(dòng)捕捉間隔設(shè)置為 5 秒鐘。
  • 4.使用ARC的項(xiàng)目,一般內(nèi)存泄漏都是 malloc、自定義結(jié)構(gòu)、資源引起的,多注意這些地方進(jìn)行分析。
  • 5.開啟ARC后,內(nèi)存泄漏的原因
    開啟了ARC并不是就不會(huì)存在內(nèi)存問題,蘋果有句名言:ARC is only for NSObject。
  • 注:如果你的項(xiàng)目使用了ARC,隨著你的操作,不斷開啟或關(guān)閉視圖,內(nèi)存可能持續(xù)上升,但這不一定表示存在內(nèi)存泄漏,ARC釋放的時(shí)機(jī)是不固定的。

做一下就簡(jiǎn)單的演示:

  • 項(xiàng)目:
    創(chuàng)建 single View App
    添加一個(gè)People 類

  • 這里選用的是MRC :

  • 在 Main.storyboard 里拖了一個(gè) 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)擊那個(gè)測(cè)試按鈕多點(diǎn)幾次 “button”,

  • 切換到 Instruments 會(huì)發(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 ThreadHide System Libraries 兩個(gè)選項(xiàng),
    Hide System Libraries 作用是隱藏系統(tǒng)函數(shù)。如果不點(diǎn)擊 這里顯示的是執(zhí)行代碼完整路徑,其中系統(tǒng)和應(yīng)用本身一些調(diào)用路徑完全揉捏在一起. 完全看不到我們關(guān)心的應(yīng)用程序中實(shí)際代碼執(zhí)行耗時(shí)和代碼路徑實(shí)際所在位置
不勾選效果如下:
勾選效果如下:

在新的版本中 Call Tree 的 這些設(shè)置換了位置 在底部左下角:




  • 勾選之后,雙擊一下就會(huì)來到內(nèi)存泄漏的地方




這里對(duì) Display Settings 中 的 Call tree 選項(xiàng)做一下說明 [官方user guide翻譯]:
  • Separate By Thread: 線程分離,只有這樣才能在調(diào)用路徑中能夠清晰看到占用CPU最大的線程.每個(gè)線程應(yīng)該分開考慮。只有這樣你才能揪出那些大量占用CPU的"重"線程,按線程分開做分析,這樣更容易揪出那些吃資源的問題線程。特別是對(duì)于主線程,它要處理和渲染所有的接口數(shù)據(jù),一旦受到阻塞,程序必然卡頓或停止響應(yīng)。

  • Invert Call Tree: 從上到下跟蹤堆棧信息.這個(gè)選項(xiàng)可以快捷的看到方法調(diào)用路徑最深方法占用CPU耗時(shí)(這意味著你看到的表中的方法,將已從第0幀開始取樣,這通常你是想要的,只有這樣你才能看到CPU中話費(fèi)時(shí)間最深的方法),比如FuncA{FunB{FunC}},勾選后堆棧以C->B->A把調(diào)用層級(jí)最深的C顯示最外面.反向輸出調(diào)用樹。把調(diào)用層級(jí)最深的方法顯示在最上面,更容易找到最耗時(shí)的操作。

  • Hide Missing Symbols:如果dSYM無法找到你的APP或者調(diào)用系統(tǒng)框架的話,那么表中將看到調(diào)用方法名只能看到16進(jìn)制的數(shù)值,勾選這個(gè)選項(xiàng)則可以隱藏這些符號(hào),便于簡(jiǎn)化分析數(shù)據(jù).

  • Hide System Libraries: 表示隱藏系統(tǒng)的函數(shù),調(diào)用這個(gè)就更有用了,勾選后耗時(shí)調(diào)用路徑只會(huì)顯示app耗時(shí)的代碼,性能分析普遍我們都比較關(guān)系自己代碼的耗時(shí)而不是系統(tǒng)的.基本是必選項(xiàng).注意有些代碼耗時(shí)也會(huì)納入系統(tǒng)層級(jí),可以進(jìn)行勾選前后前后對(duì)執(zhí)行路徑進(jìn)行比對(duì)會(huì)非常有用.因?yàn)橥ǔD阒魂P(guān)心cpu花在自己代碼上的時(shí)間不是系統(tǒng)上的,隱藏系統(tǒng)庫文件。過濾掉各種系統(tǒng)調(diào)用,只顯示自己的代碼調(diào)用。隱藏缺失符號(hào)。如果 dSYM 文件或其他系統(tǒng)架構(gòu)缺失,列表中會(huì)出現(xiàn)很多奇怪的十六進(jìn)制的數(shù)值,用此選項(xiàng)把這些干擾元素屏蔽掉,讓列表回歸清爽。

  • Show Obj-C Only: 只顯示oc代碼 ,如果你的程序是像OpenGl這樣的程序,不要勾選側(cè)向因?yàn)樗锌赡苁荂++的

  • Flatten Recursion: 遞歸函數(shù), 每個(gè)堆棧跟蹤一個(gè)條目,拼合遞歸。將同一遞歸函數(shù)產(chǎn)生的多條堆棧(因?yàn)檫f歸函數(shù)會(huì)調(diào)用自己)合并為一條。

  • Top Functions: 找到最耗時(shí)的函數(shù)或方法。 一個(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í)的方法。


需要添加其他工具的話:

進(jìn)行如下操作:



關(guān)于界面的一些其他的補(bǔ)充:
  • 左邊的Show the CPU Data 可以查看每個(gè)CPU的消耗情況
  • 中間的Show the Instruments Data 顯示整體的消耗情況
  • 右邊的Show the Thread Data 可以查看每個(gè)線程對(duì)CPU的消耗情況

選擇 Detail -> Call Tree

表示查看整個(gè)調(diào)用過程有了上面的基礎(chǔ)知識(shí)就可以對(duì)App的CPU消耗情況進(jìn)行實(shí)時(shí)檢測(cè)了。



問題分析

首先 由于 Leaks 是動(dòng)態(tài)監(jiān)測(cè),所以我們需要手動(dòng)操作 APP,進(jìn)行測(cè)試,一邊操作 APP,一邊觀察 Leaks 的變化。
也就是說 兩者必須關(guān)聯(lián)好,最為簡(jiǎ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


悼念

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容