IOS-記憶體洩漏檢測工具Instruments中的Leaks
Instruments 是一個很靈活的、強大的工具;是效能分析、動態跟蹤 和分析OS X 以及iOS程式碼的測試工具;用它可以極為方便收集關於一個或多個系統程序的效能和行為的資料,並能及時隨著時間跟蹤而產生的資料,並檢查所收集的資料,還可以廣泛收集不同型別的資料;也可以追蹤程式執行的過程,這樣instrument就可以幫助我們瞭解使用者的應用程式和作業系統的行為。
總結一下instrument能做的事情:
1.Instruments是用於動態調追蹤和分析OS X和iOS的程式碼的效能分析和測試工具;
2.Instruments支援多執行緒的除錯;
3.可以用Instruments去錄製和回放,圖形使用者介面的操作過程
4.可將錄製的圖形介面操作和Instruments儲存為模板,供以後訪問使用。
或者說:
1.追蹤程式碼中的(甚至是那些難以複製的)問題;
2.分析程式的效能;
3.實現程式的自動化測試;
4.部分實現程式的壓力測試;
5.執行系統級別的通用問題追蹤除錯;
6.使你對程式的內部執行過程更加了解。
以上資料連結
instrument 模板雖多,但常用的就那幾個(這裡也只介紹幾個常用的工具):
- Leaks(洩漏):一般的檢視記憶體使用情況,檢查洩漏的記憶體,並提供了所有活動的分配和洩漏模組的類物件分配統計資訊以及記憶體地址歷史記錄;
- Time Profiler(時間探查):執行對系統的CPU上執行的程序低負載時間為基礎取樣。
- Allocations(記憶體分配):跟蹤過程的匿名虛擬記憶體和堆的物件提供類名和可選保留/釋放歷史;
- Activity Monitor(活動監視器):顯示器處理的CPU、記憶體和網路使用情況統計;
- Blank(空模板):建立一個空的模板,可以從Library庫中新增其他模板;
- Automation(自動化):這個模板執行它模擬使用者介面互動為IOS機應用從instrument啟動的指令碼;
- Core Data:監測讀取、快取未命中、儲存等操作,能直觀顯示是否儲存次數遠超實際需要。
- Cocoa Layout:觀察約束變化,找出佈局程式碼的問題所在。
- Network:跟蹤 TCP / IP和 UDP / IP 連線。
- Automations:建立和編輯測試指令碼來自動化 iOS 應用的使用者介面測試。
Instruments最常用的三大類(主要介紹下面這三個的操作):
- Leaks:找到引發記憶體洩漏的起點
- Time Profiler:分析程式碼的執行時間,找出導致程式變慢的原因。
- Allocations:監測記憶體使用/分配情況
一、使用 Instruments [ˈɪnstrʊm(ə)nt] 的 Leaks工具 [liks 漏洞]
迅速膨脹的記憶體可以很快讓程式斃命,所以要多加防範。即使有 ARC(自動引用計數)記憶體管理機制,但在現實中物件之間引用複雜,迴圈引用導致的記憶體洩漏仍然難以避免,所以關鍵時刻還要自力更生。分析記憶體洩露不能把所有的記憶體洩露查出來,有的記憶體洩露是在執行時,使用者操作時才產生的。那就需要用到 Instruments 的leaks 了。
- Leaks 除錯解決 iOS 記憶體洩漏的工具 快捷鍵:command + control + i
開啟步驟:
1、首先我們選中Xcode先把模擬器(command + R)執行起來
2、然後我們再選中Xcode,按快捷鍵(command + control + i)執行起來, 選擇 Leaks --> Choose
或者 點選 Xcode 的 “除錯導航”
然後選中 “Memory”,再點選右側的 “Profile in Instruments”,
會自動開啟Instruments。這時候會彈出來一個對話方塊,
選擇“Transfer” 這種方式開啟
在或者你可以通過 Xcode --> Open Developer Tool --> instruments --> Leaks 的方式來開啟
再或者你可以 按著control+空格鍵,輸入instruments 開啟 (meishichulaihaha)
開啟後,這時介面如圖:
- 由於Leaks是動態監測,所以我們需要手動操作APP,進行測試,一邊操作APP,一邊觀察Leaks的變化,通過
暫停按鈕
右邊的選擇 我們可以選擇正在執行的程式,選中裝置 & App,之後點選紅點Record(紅色圓圈按鈕)執行。 - 觀察,如果發現在Leaks裡面有一個紅色X,這說明了我們的APP存在記憶體洩露。
- 點選暫停,點選其中一個,然後我們開始分析。(也可繼續檢測,當多個時暫停,一次處理了多個)
- 下面就是定位修改了,此時選中有紅色叉的Leaks,下面有個
田
字方格,點開,選中Call Tree。 - 接著就是最關鍵的一步,在這個介面的右下角有若干選框,選中Invert Call Tree 和Hide System Libraries,(紅圈範圍內)(如果不知道在那個位置請接著往下看)
- 定位
在詳情面板選中顯示的若干條中的一條,雙擊,會自動跳到記憶體洩露程式碼處,然後點選右上角 Xcode 圖示進行修改。
Leaks介面講解:
Leaks 啟動後會開始錄製,隨著對模擬器執行的App的操作,可以在Leaks中檢視記憶體佔用的情況。
Leaks頂部分為兩欄:Allocations(aləˈkeɪʃ(ə)n,分配 )和Leaks,右側的曲線代表記憶體分配和記憶體洩漏曲線。
點選第二欄Leaks,如下圖:
進行記憶體洩漏分析,右下角會出現Leaks除錯的選項:
1、Record Settings (ˈrɛkɔːd 記錄設定)
2、Display Settings 選項面板
3、Extended Detail 擴充套件面板(ɛkˈstɛnd,延展 diːteɪl,細節詳情),在時間探查儀器的情況下,它是用來跟蹤顯示堆疊。
老版本是在右邊顯示:
現在是在底部左下角:
不過在左下角有除錯時間間隔的
記憶體洩漏動態分析技巧:
1.在Display Settings 介面建議把 Snapshot Interval (snapʃɒt, 資料快照)間隔時間設定為10秒,勾選Automatic Snapshotting,Leaks會自動進行記憶體捕捉分析。
2.熟練使用Leaks後會對記憶體洩漏判斷更準確,在可能導致洩漏的操作裡,在你懷疑有記憶體洩漏的操作前和操作後,可以點選Snapshot Now進行手動捕捉。
3.開始時如果裝置效能較好,可以把自動捕捉間隔設定為5秒鐘。
4.使用ARC的專案,一般記憶體洩漏都是malloc、自定義結構、資源引起的,多注意這些地方進行分析。
5.開啟ARC後,記憶體洩漏的原因
開啟了ARC並不是就不會存在記憶體問題,蘋果有句名言:ARC is only for NSObject。
注:如果你的專案使用了ARC,隨著你的操作,不斷開啟或關閉檢視,記憶體可能持續上升,但這不一定表示存在記憶體洩漏,ARC釋放的時機是不固定的。
做一下演示:
- 檔案目錄如下:
- 這裡選用的是MRC :
- 在Main.storyboard裡拖了一個button 並且為button的“touchUpInset”事件繫結buttonClick:事件處理方法
- 在People.h檔案裡面程式碼如下
- 在UIViewController.m檔案裡面程式碼如下:
- (IBAction)buttonClick:(id)sender {
People * people = [[People alloc]init];
[people retain];
people.str = @"1324567";
}
- 執行專案,切換到iOS模擬器,點選那個測試按鈕多點幾次“button”,
- 切換到Instruments會發現 如果沒有洩漏 如圖
- 當然這裡是洩漏,在“Leaks”一欄裡有紅色的 X。如圖六這就是記憶體洩露了。
點選暫停,然後點選“Leaks”一欄
然後點選“導航欄”切換到“call tree”模式下
看到列表裡列出了記憶體洩露的呼叫邏輯:
注意:
在老版本中:
- 勾選右邊的詳細視窗 Display Settings中的 Call Tree中 Separate by Thread和 Hide System Libraries兩個選項,Hide System Libraries作用是隱藏系統函式。如果不點選 這裡顯示的是執行程式碼完整路徑,其中系統和應用本身一些呼叫路徑完全揉捏在一起.完全看不到我們關心的應用程式中實際程式碼執行耗時和程式碼路徑實際所在位置
不勾選效果如下:
勾選效果如下:
在新的版本中 Call Tree 的 這些設定換了位置 在底部左下角:
新版本:
勾選之後,雙擊一下就會來到記憶體洩漏的地方
這裡對右側Display Settings中 的 Call tree
選項有必要做一下說明 [官方user guide翻譯]:
Separate By Thread:執行緒分離,只有這樣才能在呼叫路徑中能夠清晰看到佔用CPU最大的執行緒.每個執行緒應該分開考慮。只有這樣你才能揪出那些大量佔用CPU的"重"執行緒,按執行緒分開做分析,這樣更容易揪出那些吃資源的問題執行緒。特別是對於主執行緒,它要處理和渲染所有的介面資料,一旦受到阻塞,程式必然卡頓或停止響應。
Invert Call Tree:從上到下跟蹤堆疊資訊.這個選項可以快捷的看到方法呼叫路徑最深方法佔用CPU耗時(這意味著你看到的表中的方法,將已從第0幀開始取樣,這通常你是想要的,只有這樣你才能看到CPU中話費時間最深的方法),比如FuncA{FunB{FunC}},勾選後堆疊以C->B->A把呼叫層級最深的C顯示最外面.反向輸出呼叫樹。把呼叫層級最深的方法顯示在最上面,更容易找到最耗時的操作。
Hide Missing Symbols:如果dSYM無法找到你的APP或者呼叫系統框架的話,那麼表中將看到呼叫方法名只能看到16進位制的數值,勾選這個選項則可以隱藏這些符號,便於簡化分析資料.
Hide System Libraries:表示隱藏系統的函式,呼叫這個就更有用了,勾選後耗時呼叫路徑只會顯示app耗時的程式碼,效能分析普遍我們都比較關係自己程式碼的耗時而不是系統的.基本是必選項.注意有些程式碼耗時也會納入系統層級,可以進行勾選前後前後對執行路徑進行比對會非常有用.因為通常你只關心cpu花在自己程式碼上的時間不是系統上的,隱藏系統庫檔案。過濾掉各種系統呼叫,只顯示自己的程式碼呼叫。隱藏缺失符號。如果 dSYM 檔案或其他系統架構缺失,列表中會出現很多奇怪的十六進位制的數值,用此選項把這些干擾元素遮蔽掉,讓列表迴歸清爽。
Show Obj-C Only: 只顯示oc程式碼 ,如果你的程式是像OpenGl這樣的程式,不要勾選側向因為他有可能是C++的
Flatten Recursion: 遞迴函式, 每個堆疊跟蹤一個條目,拼合遞迴。將同一遞迴函式產生的多條堆疊(因為遞迴函式會呼叫自己)合併為一條。
Top Functions:找到最耗時的函式或方法。 一個函式花費的時間直接在該函式中的總和,以及在函式呼叫該函式所花費的時間的總時間。因此,如果函式A呼叫B,那麼A的時間報告在A花費的時間加上B.花費的時間,這非常真有用,因為它可以讓你每次下到呼叫堆疊時挑最大的時間數字,歸零在你最耗時的方法。
需要新增其他工具的話:
進行如下操作:
關於介面的一些其他的補充:
- 左邊的Show the CPU Data 可以檢視每個CPU的消耗情況
- 中間的Show the Instruments Data 顯示整體的消耗情況
- 右邊的Show the Thread Data 可以檢視每個執行緒對CPU的消耗情況
選擇 Detail -> Call Tree
表示檢視整個呼叫過程有了上面的基礎知識就可以對App的CPU消耗情況進行實時檢測了。