iOS技術(shù)文檔No.22 Foundation_NSAutoreleasePool

一、背景
要想深入了解autorelease pool的原理,推薦以下兩片文章即可:
Using Autorelease Pool Blocks
Objective-C Autorelease Pool 的實現(xiàn)原理
要想掌握上文中的要點,還是要廢不少勁的。對于這種原理比較抽象,和實際開發(fā)編碼沒有直接關(guān)系的原理性的東西,常常是看一遍過一陣子很快就忘得了,為了加深印象,還是有必要系統(tǒng)性地梳理一遍,簡單化地總結(jié)一下,加深一下印象。以下筆記也是基于以上兩處文獻進行總結(jié)的。
二、Autorelease Pool使用場景
1、降低內(nèi)存使用峰值:
這一點不用多說,當(dāng)你使用類似for循環(huán)這樣的邏輯需要產(chǎn)生大量的中間變量時,Autorelease Pool無意是最佳的一種解決方案;
2、如果是對NSArray操作,如果可以的話推薦使用OC提供的以下api:

  • (void)enumerateObjectsUsingBlock:

  • (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:

  • (void)enumerateObjectsAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts usingBlock:
    如果你debug一下源碼就該知道為什么推薦使用它們了(內(nèi)部封裝了autoreleasepool),我們debug看一下:然后在采取以下命令跟蹤string_weak_的值變化,如下:


    再點開enumerateObjectsUsingBlock的執(zhí)行堆棧信息,看一下:


如果你再debug一下普通的for循環(huán)就不會有這些push和pop,既然enumerateObjectsUsingBlock內(nèi)部有了autoreleasepool,為什么推薦使用它的原因就不多說了。
3、按照蘋果給的文檔說的,如果采取一些非cocoa創(chuàng)建的一些線程,將不會自動生成autoreleasepool給你,你需要手動去創(chuàng)建它。
三、Autorelease Pool的實現(xiàn)原理
1、Autoreleasepool的結(jié)構(gòu)
每個Cocoa的線程都會默認標(biāo)配一個Autorelease Pool,但是你也可以手動創(chuàng)建多個。從前面的操作中,也應(yīng)該能隱約猜出來了些許,有push和pop操作,意味著每個pool的管理其實是一種類似棧結(jié)構(gòu)的進棧出棧操作,當(dāng)然pool的管理更復(fù)雜些,因為它可以創(chuàng)建多個,還可以嵌套創(chuàng)建刪除。這種情況,普通的棧結(jié)構(gòu)是無法滿足這種需求的。如下的代碼結(jié)構(gòu):

Pool的創(chuàng)建順序:Pool 1 ---> Pool 2 ---> Pool 3,drain順序是Pool 2 ---> Pool 1 --->Pool 3,如果要想實現(xiàn)這種順序,采取FIFO做不到,普通的棧也不行。如果用鏈表操作可以做到,因為涉及到鏈表的首(Pool 2)或尾(Pool 3)插入,應(yīng)該用雙向鏈表來管理才合適。如下:

有人可能會有疑問,順序為什么不是1、2、3,我覺得這些問題都不大,上面的順序Push鏈表的復(fù)雜度為O(n),Pop的復(fù)雜度為O(1),反過來的話,
就是Push鏈表的復(fù)雜度為O(1),Pop的復(fù)雜度為O(n),如果糾結(jié)這個的可以去擼源碼。
2、AutoreleasePoolPage的結(jié)構(gòu)
上面介紹了,每個線程的Pool結(jié)構(gòu)層次,其實是有多個PoolPage構(gòu)成。
ARC下會對其中的對象會隱式執(zhí)行autorelease操作,autorelease操作將一個指向?qū)ο髮嵗膶ο笾羔樚砑拥絇oolPage中。

添加的過程如下:

當(dāng)當(dāng)前PoolPage作用域一過,就會對從線程pool中執(zhí)行pop操作,而pop操作,pop的過程,會遍歷page堆棧,對指向的對象一一執(zhí)行release操作,如果對象的retainCount變?yōu)?,即立即釋放,如果對象的retaiCount大于0,不釋放。當(dāng)所有對象處理完(出棧完畢),最后完成pop操作。
四、為什么有了ARC還要Autorelease Pool?
這個問題之前我也想過,搜了下,沒有感覺回答滿意的,也沒找到蘋果的官方回答,這里只能自給妄自推斷一下。提到OC的RC,首先要橫向?qū)Ρ纫幌?a target="_blank" rel="nofollow">Android的GC,GC的內(nèi)存回收是集中式回收(定期回收),而RC的回收是伴隨整個運行時的,所以android機器有種時“卡”時“流暢”的感覺,而iOS總體比較均勻,缺乏像GC的集中式回收內(nèi)存的類似機制,所以猜測Pool的產(chǎn)生也是彌補RC的這一不足,在RC基礎(chǔ)上進行內(nèi)存優(yōu)化的一種手段。

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

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

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