版權聲明:本文由胡濤原創文章,轉載請注明出處:
文章原文鏈接:https://www.qcloud.com/community/article/125
來源:騰雲閣 https://www.qcloud.com/community
使用instruments工具來更好的調試我們的工程中新開發或者修改過的模塊的內存狀況。
iOS設備性能越來越好,iOS App 也相應的變得越來越龐大,App代碼的量級也在快速的增長,開發一個小的模塊在工程中調試變的越來越難,通常我們是通過觀察Allocation的內存變化高低,或者內存分配快照對比來尋找泄漏的情況,但這幾乎是一個讓人抓狂的調試方法,尤其在非常復雜的項目中,一個模塊的推入與推出在Allocation上的變化微乎其微,而且受制於項目的復雜度,各種你所未知的對象的創建與銷毀帶來的Allocation圖形高度的影響,對於觀察Allocation的分配圖像的高低變化來說,能夠參考的意義就變的非常有限。
通過過去參與過的復雜大型的iOS項目開發經驗,開發新的模塊的時候,總結出了一套完整的iOS內存自測的方法,通過Instruments來逐步跟蹤檢測我們創建和主動銷毀的對象是否真的銷毀了。
在演示之前,需要強調一件事情就是,以文件夾目錄作為你的空間命名很重要,請遵循開發新模塊的時候使用你的模塊的命名作為前綴。因為iOS沒有命名空間這個東西,通常為了保證不沖突,我們都是以項目前綴+空間命名來保證文件的獨立性,空間名就是目錄和模塊的名字了。這個在我們使用instruments進行內存檢測的時候是非常重要的,接下來的使用過程就可以證實這一良好的命名習慣所帶來的巨大好處,不只是優雅,更重要的是幫助。
除了命名,還有一件很重要的事情就是,你需要對你的模塊在各種UI操作或者事件發生過程的情況下,對你的對象分配過程要非常非常清楚,因為這樣,你才能看出相應的變化,哪些對象是應該存在的,哪些對象在某個動作結束后是必定會銷毀的,這個應該很容易,你應該純天然的就知道,因為你開發的整個邏輯。
最近在開發一個新的模塊,正好需要在內存方面做一個完整的自測,既要確保效率,也要確保內存的正確分配與釋放。
重要:(以下教程開始所有示例圖片,請自行點擊圖片看大圖,看的倍兒清楚!)
-
首先,我先上圖,看一下我的命名組織結構,遵循的就是模塊化的命名,因為手Q的跨部門合作,所以用部門標記作為前綴。代碼首先是要讓人來看的,是人在維護程序,所以可讀性非常重要,在開發完這些功能后,我對於所有對象在運行過程中的創建與銷毀是很清楚的。

-
接下來我要進入instruments來進行內存測試,profile運行Leaks就OK了,就會進入下面看到的界面,詳細講解一下都是什么吧,這些對對象怎么分配內存的很重要。

-
然后我就需要操作模擬器來進入我所開發的功能模塊,會看到非常復雜的對象分配情況,所以這一步非常關鍵,我只需要在搜索框搜索模塊的前綴就可以只顯示當前模塊所涉及的對象分配與銷毀情況,如下圖,進入了的模塊視圖:

-
接下來我執行一個環境查詢的命令,再看一下執行之后的內存分配情況。

-
我的邏輯是這樣的,點擊一次創建一個命令(VASDebugPlatformServerCmd),通過這個命令初始化並執行一個任務,任務結束后就銷毀這個任務對象(VASDebugPlatformBaseOperation),相應的命令也作為任務的成員一起被銷毀。所以,在動作執行完后我們應該可以在已銷毀對象中找到這個實例,運行截圖如下:

-
我看到任務是已經被銷毀了的,可是用來初始化的命令對象為什么沒有被銷毀,我需要深挖一下這個命令對象(VASDebugPlatformServerCmd)的引用計數到底怎么發生變化的,就需要用到下面的步驟了,按照圖解去深挖它:

-
我挖到命令對象的內部,一路挖到底,我發現命令對象最終的引用計數是1,證明它還在內存中活着,截圖是這樣的:

-
所以,我就看看,任務對象銷毀了,那任務對象到底發生了什么事 截圖是這樣的:

-
我就是不死心,我就是要看到,到底是不是真的呢,為了進一步佐證命令對象在內存中,我在對象內部觀察了一個內存檢測的通知,收到通知后彈一個alert出來,如果對象被銷毀了,它肯定收不到這個通知,如下面截圖所示的工作:

-
因為這是我自己寫的邏輯,我很清楚對象在哪里分配內存,然后我就去查代碼,命令對象到底經歷了什么,從開始到結束的執行過程是什么樣的:



- 看完上面的截圖,再去看命令對象的引用計數變化就知道為什么了:

- 當然,我也看出了為什么引用計數沒有歸零,所以,我在下面進行了修復:

- 再次profile->Leaks , 然后我再做一次查詢任務,看看這次命令對象的引用計數變化,命令對象被釋放了!:


總結:
-
保持你的模塊擁有一個良好的命名空間
-
請深刻並且清楚的知道,觸發什么事件,執行UI動作之后,你的對象分配會是什么樣的,誰此刻應該存在內存中,誰應該被銷毀,然后利用上面的原理去查看,它是不是被銷毀了,如果沒有被銷毀,那么你應該去查你的代碼,到底在執行過程中,哪里沒有平衡引用計數。
-
此方法在ARC和MRC的情況都是適用的,目標是觀察具體哪個實例對象沒有被銷毀,然后根據引用計數變化跳轉到代碼中去確認哪里出現了內存問題。
文章來源於公眾號:小時光茶社(Tech Teahouse)
