性能優(yōu)化-內(nèi)存管理2

MRC&ARC

ARC是LLVM和Runtime配合的結(jié)果
ARC中禁?止?手動調(diào)?用retain/release/retainCount/dealloc
ARC新加了了weak、strong屬性關(guān)鍵字

alloc出來的引用計數(shù)是多少?

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        LGPerson *p = [LGPerson alloc];
        NSLog(@"%lu",(unsigned long)[p retainCount]); 
     }
    return 0;
}

打印出的結(jié)果是1
這個時候 我們?nèi)ゲ榭磖etainCount的底層

RetainCount

全局搜索retainCount


image.png

image.png

由retainCount源碼看出返回的rc是isa.bits.extra_rc + 1所得到的 再次 因為打印出來的結(jié)果是1 那么就認為isa.bits.extra_rc = 0 也就是該對象的引用計數(shù)在alloc之后是0

引用計數(shù)在什么時候會加 什么時候會減

Retain

全局搜索retain


image.png

image.png

image.png

image.png
引用計數(shù)表的前兩位存的不是引用計數(shù)  第一位存的是是否為弱引用的標識 第二位存的是是否正在deallocating
Release

當引用計數(shù)為0的時候 會走析構(gòu)方法 這個是必要條件 不是充分條件
全局搜索release

image.png

image.png

image.png

如果走析構(gòu)函數(shù) 就會給這個對象發(fā)送dealloc消息
release是先對isa.bits.extra_rc進行減一操作 如果沒有下溢出的話就結(jié)束
如果有下溢出的話 就去查看散列表是否存放了引用計數(shù) 如果有的話 就取出散列表中存放的那一半空間的引用計數(shù)進行減一操作然后存放到extra_rc中 結(jié)束
如果散列表中沒有存放引用計數(shù) 就發(fā)送dealloc消息

為什么當引用計數(shù)超的時候 放一半到散列表?

1 當extra_rc都存放滿的時候 如果全部放到散列表中 等下次extra_rc滿了 再次放到散列表 會造成當對這個對象進行release操作的時候 由于extra_rc沒有值的話 就會對散列表進行操作 造成對散列表的操作過于頻繁 從而影響到性能
2 一半正好是位移操作的一個位置  便于直接簡單操作 左移右移一位 能夠直接定位
3. 不大不小 正好合適 對于retain release來說

retain 相應的引用計數(shù)加1
release 相應的引用計數(shù)減一

dealloc應該做一些什么事情

weak

image.png

全局搜索objc_initWeak
image.png

如果弱引用表中有weak對象 就remove
image.png

image.png

image.png

如果弱引用表中沒有weak對象
1.就進行weak_register_no_lock操作
image.png

2.創(chuàng)建entry
@如果weak_entries不存在的話 就直接返回
如果存在的話 就找到那個原先沒有存放過entry的位置 返回這個位置的entry
image.png

如果這個entry是存在的話 就執(zhí)行append_referrer(entry, referrer);方法
在這個方法中 就是把這個弱引用的指針存放在entry的inline_referrers數(shù)組,同時要把這個弱引用的指針存放在new_referrers數(shù)組里面 也要賦值給entry的referrers變量
3.如果entry無法創(chuàng)建的話
image.png

@新建一個entry
@如果weakTable的entrys里面存放的值的大小的3/4已經(jīng)達到了weakTable設置的num_entryies的大小 那么久會擴容
image.png

@然后把entry加入到weak_entries里面 同時num_entries進行加一操作
image.png

有一步操作需要注意: 在新建entry的時候?qū)λ膇nline_referrers數(shù)組進行了初始化 把weak對象和entry聯(lián)系起來了
image.png

weak對引用計數(shù)不操作
weak流程圖.png

1:拿到sideTable 
2:得到sideTable的weakTable 弱引?用表 
3:創(chuàng)建?一個weak_entry_t 
4:把referent加?入到weak_entry_t的數(shù)組inline_referrers 
5:把weak_table擴容?一下
6:把new_entry加?入到weak_table中
dealloc

全局搜索dealloc


image.png

如果他沒有弱引用 沒有關(guān)聯(lián)對象 沒有c++函數(shù) 散列表里面沒有放引用計數(shù)的話 直接free 否則 object_dispose


image.png

如果有C++函數(shù) 或者如果有關(guān)聯(lián)對象 直接remove 然后再執(zhí)行clearDeallocating
image.png

image.png

image.png

image.png

image.png

image.png

1:根據(jù)當前對象的狀態(tài)是否直接調(diào)?用free()釋放
2:是否存在C++的析構(gòu)函數(shù)、移除這個對象的關(guān)聯(lián)屬性
3:將指向該對象的弱引?用指針置為nil
4:從弱引?用表中擦除對該對象的引?用計數(shù)

Strong

全局搜索objc_storeStrong
retain新值 release舊值


image.png

objc_ivar_memoryUnretained不是指針的傳遞 是對象的傳遞 也就說value為nil的話
*location 就是野指針 浪費空間 這就是unsafe不安全的原因


image.png

自動釋放池

自動釋放池: 容納變量 在合適的位置釋放
在何時使用?

1.大量的臨時變量
2.非UI操作 命令行代碼
3.自己創(chuàng)建輔助線程

查看cpp代碼

1.cd 到main存在的目錄
2.終端執(zhí)行clang -rewrite-objc main.m -o main.cpp
3.打開main.cpp
struct __AtAutoreleasePool {
  //產(chǎn)生一個atautoreleasepoolobj對象
  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
  //析構(gòu)函數(shù)
  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
  void * atautoreleasepoolobj;
};

全局搜索objc_autoreleasePoolPush


image.png

autoreleasePoolPage 屬性占用的字節(jié)為56個


image.png

image.png

image.png

一頁所能容納的大小 是 4096


image.png

image.png

image.png

image.png

image.png

一共可以容納4096個字節(jié) 減掉本身占用的56個字節(jié) 剩下4040個字節(jié) 每個變量占用8個字節(jié) 也就是可以容納505個

全局搜索_objc_autoreleasePoolPrint


image.png

image.png

image.png

4096個大小 有56個屬性 進行壓棧之前要開辟一個邊界符然后繼續(xù)壓棧 直到這個頁面滿了之后 開辟新的頁面 還是要先開辟一個邊界符

autorelease

全局搜索autorelease {


image.png

直接執(zhí)行autoreleaseFast方法


image.png

image.png

Push
1.有頁面但是滿了 - 創(chuàng)建新的頁面 老頁面的child指針指向新的頁面 新界面的parent指針指向老頁面
2.有頁面但是沒有滿 直接加入進去
3.一個頁面都沒有 創(chuàng)建新的界面
都執(zhí)行add(objc) *next++ = objc

pop

全局搜索pop


image.png

image.png

id obj = *--page->next;
都執(zhí)行release(objc)

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

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