本文章主要介紹的是 Instruments 的相關知識,以及如何使用Instruments的 Leaks 工具。 Instruments 其它的工具會在后面篇文章一一介紹.
前言介紹:
或許很多朋友對Instruments應用不太了解,但可能很多老的iOS開發(fā)者都應該用過Instruments工具來檢測iOS應用內存泄漏情況。特別是在iOS 5.0之前,即蘋果在iOS平臺上面還沒支持ARC的時候,寫iOS應用就類似C語言那樣,容易忘記釋放內存,而內存對移動設備而言是非??少F的。即使目前iPhone設備內存已經(jīng)滿足512MB了,但是因為蘋果的后臺模式是把整個應用封裝起來等待下次啟用,所以該應用所占用的內存同樣被占據(jù)了。也就是即使應用進入后臺模式,它還是仍然占用原先的內存的,所以你打開的應用越多,內存耗用自然也很多。對很多普通用戶而言,往往他們打開的應用都是進入后臺模式的,很少有用戶清理后臺的應用,所以也就造成很多應用其實可用內存還是非常有限地 (題外話:如果蘋果原生支持一鍵清理后臺程序就好了,貌似越獄的工具里面有這樣的支持的。
還有做過iOS應用自動化測試的開發(fā)者,應該對UIAutomation很熟悉吧。它就是通過JS腳本來寫界面自動化測試用例。而Instruments應用對UIAutomation支持很完善,你可以通過它查看很多代碼潛在的問題,并測試性能。
其實Instruments應用還有很多強大的功能,它原生支持很多instrument工具,幫助你分析你的代碼,不僅包括內存檢測和自動化測試,它還可以監(jiān)測文件讀寫操作等等。所以一個好的iOS開發(fā)者是應該掌握Instrument應用的使用。因為Instruments應用本身功能太強大的,所以完全掌握機會不可能,但是因為它們內置的很多工具具有相似性,所以基本掌握自己常用的即可。同時了解一下內部有哪些功能,這樣在你需要用到的時候再查查文檔,就可以很快上手了。
正文 Instruments 的介紹:
Instruments 是一個很靈活的、強大的工具;是性能分析、動態(tài)跟蹤 和分析OS X 以及iOS代碼的測試工具;用它可以極為方便收集關于一個或多個系統(tǒng)進程的性能和行為的數(shù)據(jù),并能及時隨著時間跟蹤而產(chǎn)生的數(shù)據(jù),并檢查所收集的數(shù)據(jù),還可以廣泛收集不同類型的數(shù)據(jù);也可以追蹤程序運行的過程,這樣instrument就可以幫助我們了解用戶的應用程序和操作系統(tǒng)的行為。
總結一下instrument能做的事情:
1.Instruments是用于動態(tài)調追蹤和分析OS X和iOS的代碼的性能分析和測試工具;
2.Instruments支持多線程的調試;
3.可以用Instruments去錄制和回放,圖形用戶界面的操作過程
4.可將錄制的圖形界面操作和Instruments保存為模板,供以后訪問使用。
或者說:
1.追蹤代碼中的(甚至是那些難以復制的)問題;
2.分析程序的性能;
3.實現(xiàn)程序的自動化測試;
4.部分實現(xiàn)程序的壓力測試;
5.執(zhí)行系統(tǒng)級別的通用問題追蹤調試;
6.使你對程序的內部運行過程更加了解。
instrument 模板雖多,但常用的就那幾個(這里也只介紹幾個常用的工具):
Leaks(泄漏):一般的查看內存使用情況,檢查泄漏的內存,并提供了所有活動的分配和泄漏模塊的類對象分配統(tǒng)計信息以及內存地址歷史記錄;
Time Profiler(時間探查):執(zhí)行對系統(tǒng)的CPU上運行的進程低負載時間為基礎采樣。
Allocations(內存分配):跟蹤過程的匿名虛擬內存和堆的對象提供類名和可選保留/釋放歷史;
Activity Monitor(活動監(jiān)視器):顯示器處理的CPU、內存和網(wǎng)絡使用情況統(tǒng)計;
Blank(空模板):創(chuàng)建一個空的模板,可以從Library庫中添加其他模板;
Automation(自動化):這個模板執(zhí)行它模擬用戶界面交互為IOS機應用從instrument啟動的腳本;
Core Data:監(jiān)測讀取、緩存未命中、保存等操作,能直觀顯示是否保存次數(shù)遠超實際需要。
Cocoa Layout:觀察約束變化,找出布局代碼的問題所在。
Network:跟蹤 TCP / IP和 UDP / IP 連接。
Automations:創(chuàng)建和編輯測試腳本來自動化 iOS 應用的用戶界面測試。
Instruments最常用的三大類(主要介紹下面這三個的操作):
Leaks:找到引發(fā)內存泄漏的起點
Time Profiler:分析代碼的執(zhí)行時間,找出導致程序變慢的原因。
Allocations:監(jiān)測內存使用/分配情況
一、使用 Instruments [??nstr?m(?)nt]? 的 Leaks工具 [liks 漏洞]
迅速膨脹的內存可以很快讓程序斃命,所以要多加防范。即使有 ARC(自動引用計數(shù))內存管理機制,但在現(xiàn)實中對象之間引用復雜,循環(huán)引用導致的內存泄漏仍然難以避免,所以關鍵時刻還要自力更生。分析內存泄露不能把所有的內存泄露查出來,有的內存泄露是在運行時,用戶操作時才產(chǎn)生的。那就需要用到 Instruments 的leaks 了。
Leaks 調試解決 iOS 內存泄漏的工具 快捷鍵:command + control + i
打開步驟:
首先我們選中Xcode先把模擬器(command + R)運行起來
然后我們再選中Xcode,按快捷鍵(command + control + i)運行起來, 選擇 Leaks --> Choose

或者 點擊 Xcode 的 “調試導航”

然后選中 “Memory”,再點擊右側的 “Profile in Instruments”,

會自動打開Instruments。這時候會彈出來一個對話框,

選擇“Transfer” 這種方式打開
在或者你可以通過 Xcode --> Open Developer Tool --> instruments --> Leaks 的方式來打開

再或者你可以 按著control+空格鍵,輸入instruments 打開 (meishichulaihaha)
打開后,這時界面如圖:

由于Leaks是動態(tài)監(jiān)測,所以我們需要手動操作APP,進行測試,一邊操作APP,一邊觀察Leaks的變化,通過暫停按鈕右邊的選擇 我們可以選擇正在運行的程序,選中設備 & App,之后點擊紅點Record(紅色圓圈按鈕)運行。
觀察,如果發(fā)現(xiàn)在Leaks里面有一個紅色X,這說明了我們的APP存在內存泄露。
點擊暫停,點擊其中一個,然后我們開始分析。(也可繼續(xù)檢測,當多個時暫停,一次處理了多個)
下面就是定位修改了,此時選中有紅色叉的Leaks,下面有個田字方格,點開,選中Call Tree。
接著就是最關鍵的一步,在這個界面的右下角有若干選框,選中Invert Call Tree 和Hide System Libraries,(紅圈范圍內)(如果不知道在那個位置請接著往下看)
定位
在詳情面板選中顯示的若干條中的一條,雙擊,會自動跳到內存泄露代碼處,然后點擊右上角 Xcode 圖標進行修改。
Leaks界面講解:
Leaks 啟動后會開始錄制,隨著對模擬器運行的App的操作,可以在Leaks中查看內存占用的情況。
Leaks頂部分為兩欄:Allocations(al??ke??(?)n,分配 )和Leaks,右側的曲線代表內存分配和內存泄漏曲線。
點擊第二欄Leaks,如下圖:

進行內存泄漏分析,右下角會出現(xiàn)Leaks調試的選項:

1、Record Settings? (?r?k??d 記錄設置)
2、Display Settings 選項面板
3、Extended Detail? 擴展面板(?k?st?nd,延展? di?te?l,細節(jié)詳情),在時間探查儀器的情況下,它是用來跟蹤顯示堆棧。
老版本是在右邊顯示:

現(xiàn)在是在底部左下角:

不過在左下角有調試時間間隔的

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

這里選用的是MRC :

在Main.storyboard里拖了一個button 并且為button的“touchUpInset”事件綁定buttonClick:事件處理方法
在People.h文件里面代碼如下

在UIViewController.m文件里面代碼如下:
- (IBAction)buttonClick:(id)sender {? ? People * people = [[People alloc]init];? ? [peopleretain];? ? people.str =@"1324567";}
運行項目,切換到iOS模擬器,點擊那個測試按鈕多點幾次“button”,
切換到Instruments會發(fā)現(xiàn) 如果沒有泄漏 如圖

當然這里是泄漏,在“Leaks”一欄里有紅色的 X。如圖六這就是內存泄露了。

點擊暫停,然后點擊“Leaks”一欄
然后點擊“導航欄”切換到“call tree”模式下

看到列表里列出了內存泄露的調用邏輯:

注意:
在老版本中:
勾選右邊的詳細窗口 Display Settings中的 Call Tree中 Separate by Thread和 Hide System Libraries兩個選項,Hide System Libraries作用是隱藏系統(tǒng)函數(shù)。如果不點擊 這里顯示的是執(zhí)行代碼完整路徑,其中系統(tǒng)和應用本身一些調用路徑完全揉捏在一起.完全看不到我們關心的應用程序中實際代碼執(zhí)行耗時和代碼路徑實際所在位置

不勾選效果如下:

勾選效果如下:

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



新版本:

勾選之后,雙擊一下就會來到內存泄漏的地方


這里對右側Display Settings中 的Call tree選項有必要做一下說明 [官方user guide翻譯]:
Separate By Thread:線程分離,只有這樣才能在調用路徑中能夠清晰看到占用CPU最大的線程.每個線程應該分開考慮。只有這樣你才能揪出那些大量占用CPU的"重"線程,按線程分開做分析,這樣更容易揪出那些吃資源的問題線程。特別是對于主線程,它要處理和渲染所有的接口數(shù)據(jù),一旦受到阻塞,程序必然卡頓或停止響應。
Invert Call Tree:從上到下跟蹤堆棧信息.這個選項可以快捷的看到方法調用路徑最深方法占用CPU耗時(這意味著你看到的表中的方法,將已從第0幀開始取樣,這通常你是想要的,只有這樣你才能看到CPU中話費時間最深的方法),比如FuncA{FunB{FunC}},勾選后堆棧以C->B->A把調用層級最深的C顯示最外面.反向輸出調用樹。把調用層級最深的方法顯示在最上面,更容易找到最耗時的操作。
Hide Missing Symbols:如果dSYM無法找到你的APP或者調用系統(tǒng)框架的話,那么表中將看到調用方法名只能看到16進制的數(shù)值,勾選這個選項則可以隱藏這些符號,便于簡化分析數(shù)據(jù).
Hide System Libraries:表示隱藏系統(tǒng)的函數(shù),調用這個就更有用了,勾選后耗時調用路徑只會顯示app耗時的代碼,性能分析普遍我們都比較關系自己代碼的耗時而不是系統(tǒng)的.基本是必選項.注意有些代碼耗時也會納入系統(tǒng)層級,可以進行勾選前后前后對執(zhí)行路徑進行比對會非常有用.因為通常你只關心cpu花在自己代碼上的時間不是系統(tǒng)上的,隱藏系統(tǒng)庫文件。過濾掉各種系統(tǒng)調用,只顯示自己的代碼調用。隱藏缺失符號。如果 dSYM 文件或其他系統(tǒng)架構缺失,列表中會出現(xiàn)很多奇怪的十六進制的數(shù)值,用此選項把這些干擾元素屏蔽掉,讓列表回歸清爽。
Show Obj-C Only: 只顯示oc代碼 ,如果你的程序是像OpenGl這樣的程序,不要勾選側向因為他有可能是C++的
Flatten Recursion: 遞歸函數(shù), 每個堆棧跟蹤一個條目,拼合遞歸。將同一遞歸函數(shù)產(chǎn)生的多條堆棧(因為遞歸函數(shù)會調用自己)合并為一條。
Top Functions:找到最耗時的函數(shù)或方法。 一個函數(shù)花費的時間直接在該函數(shù)中的總和,以及在函數(shù)調用該函數(shù)所花費的時間的總時間。因此,如果函數(shù)A調用B,那么A的時間報告在A花費的時間加上B.花費的時間,這非常真有用,因為它可以讓你每次下到調用堆棧時挑最大的時間數(shù)字,歸零在你最耗時的方法。
需要添加其他工具的話:
進行如下操作:

關于界面的一些其他的補充:

左邊的Show the CPU Data? ? ? ? 可以查看每個CPU的消耗情況
中間的Show the Instruments Data 顯示整體的消耗情況
右邊的Show the Thread Data? ? ? 可以查看每個線程對CPU的消耗情況
選擇 Detail -> Call Tree

表示查看整個調用過程有了上面的基礎知識就可以對App的CPU消耗情況進行實時檢測了。
鏈接:http://www.itdecent.cn/p/92cd90e65d4c