前言
從一句代碼說(shuō)起:NSNumber *num = @(20);
只需要存儲(chǔ)20這個(gè)數(shù)據(jù)。
按正常的技術(shù)方案,在64位CPU下挂谍,應(yīng)該先去創(chuàng)建NSNumber
對(duì)象,其值是20瞎饲,然后再有個(gè)指向該地址的指針num口叙。 雖然沒有什么問題,但是造成了浪費(fèi)嗅战。
內(nèi)存浪費(fèi)
由于OC中的內(nèi)存對(duì)齊妄田,在64位下,創(chuàng)建一個(gè)對(duì)象至少16字節(jié)驮捍,再加上一個(gè)指針8個(gè)字節(jié)疟呐,總共24字節(jié)。也就是說(shuō)东且,為了存儲(chǔ)這個(gè)20而需要24字節(jié)启具,對(duì)內(nèi)存方面是極大的浪費(fèi)。性能浪費(fèi)
為了存儲(chǔ)和訪問一個(gè)NSNumber
對(duì)象苇倡,需要在堆上為其分配內(nèi)存富纸,另外還要維護(hù)它的引用計(jì)數(shù),管理生命期旨椒。這些都給程序增加了額外的邏輯晓褪,造成運(yùn)行效率上的損失。
Tagged Pointer技術(shù)
為了解決這個(gè)問題综慎,蘋果提出了Tagged Pointer的概念涣仿。
從64bit開始,iOS引入了Tagged Pointer技術(shù),用于優(yōu)化NSNumber好港、NSDate愉镰、NSString
等小對(duì)象的存儲(chǔ)。引入后钧汹,相關(guān)邏輯能減少一半的內(nèi)存占用丈探,以及 3 倍的訪問速度提升,100 倍的創(chuàng)建拔莱、銷毀速度提升碗降。
- 原理
將數(shù)據(jù) 直接存儲(chǔ)在指針中。當(dāng)指針不夠存儲(chǔ)數(shù)據(jù)時(shí)塘秦,才會(huì)使用動(dòng)態(tài)分配內(nèi)存的方式來(lái)存儲(chǔ)數(shù)據(jù)讼渊。
也就是使用Tagged Pointer之后,
NSNumber
指針里面存儲(chǔ)的數(shù)據(jù)變成了:Tag + Data
尊剔,
objc_msgSend()
函數(shù)能識(shí)別Tagged Pointer爪幻,比如NSNumber
的intValue
方法,直接從指針提取數(shù)據(jù)须误,節(jié)省了以前的調(diào)用開銷挨稿。
之前,
NSNumber
等對(duì)象需要?jiǎng)討B(tài)分配內(nèi)存京痢、維護(hù)引用計(jì)數(shù)等叶组,NSNumber
指針存儲(chǔ)的是堆中NSNumber
對(duì)象的地址值。