iOS標(biāo)記指針(Tagged Pointer)技術(shù) - 引用文章

在2013年9月,蘋果推出了iPhone5s,配備了首個采用64位架構(gòu)的A7雙核處理器筒占,為了節(jié)省內(nèi)存和提高執(zhí)行效率,蘋果提出了標(biāo)記指針(Tagged Pointer)
的概念蜘犁。對于64位程序翰苫,引入Tagged Pointer后,相關(guān)邏輯能減少一半的內(nèi)存占用沽瘦,以及3倍的訪問速度提升革骨,100倍的創(chuàng)建、銷毀速度提升析恋。

原有的對象為什么會浪費(fèi)內(nèi)存良哲?

假設(shè)我們要存儲一個NSNumber對象,其值是一個整數(shù)助隧。正常情況下筑凫,如果這個整數(shù)只是一個NSInteger的普通變量,那么它所占用的內(nèi)存是與CPU的位數(shù)有關(guān)并村,在32位CPU下占4個字節(jié)巍实,在64位CPU下是占8個字節(jié)的。而指針類型的大小通常也是與CPU位數(shù)相關(guān)哩牍,一個指針?biāo)加玫膬?nèi)存在32位CPU下為4個字節(jié)棚潦,在64位CPU下也是8個字節(jié)。

所以一個普通的iOS程序膝昆,如果沒有Tagged Pointer對象丸边,從32位機(jī)器遷移到64位機(jī)器中后,雖然邏輯沒有任何變化荚孵,但這種NSNumber妹窖、NSDate一類的對象所占用的內(nèi)存會翻倍。

效率上的問題收叶,為了存儲和訪問一個NSNumber對象骄呼,需要在堆上為其分配內(nèi)存,另外還要維護(hù)它的引用計數(shù)判没,管理它的生命期蜓萄。這些都給程序增加了額外的邏輯,造成運(yùn)行效率上的損失哆致。

  • Tagged Pointer

為了改進(jìn)上面提到的內(nèi)存占用和效率問題绕德,蘋果提出了Tagged Pointer對象。由于NSNumber摊阀、NSDate一類的變量本身的值需要占用的內(nèi)存大小常常不需要8個字節(jié)耻蛇,拿整數(shù)來說,4個字節(jié)所能表示的有符號整數(shù)就可以達(dá)到20多億(注:2^31=2147483648胞此,另外1位作為符號位)臣咖,對于絕大多數(shù)情況都是可以處理的。

  • NSNumber的優(yōu)化
    Tagged Pointer一個比較典型的應(yīng)用就是NSNumber漱牵,在64位環(huán)境下夺蛇,對于一般的數(shù)字,NSNumber不用再分配內(nèi)存了酣胀。我們看看NSNumber是如何運(yùn)用Tagged Pointer的:
NSNumber *number1=@1;
NSNumber *number2=@2;
NSNumber *number3=@3;

NSLog(@"number1 pointer is %p", number1);
NSLog(@"number2 pointer is %p", number2);
NSLog(@"number3 pointer is %p", number3);

在64位模擬器中運(yùn)行后刁赦,我得到了如下結(jié)果:

number1 pointer is 0xb000000000000012
number2 pointer is 0xb000000000000022
number3 pointer is 0xb000000000000032

可以看出number1娶聘、number2和number3的值前4位都是0xb,后4位都是0x2(指針的Tag)甚脉,中間就是實(shí)際的取值丸升,因此,這些NSNumber已經(jīng)不需要再分配內(nèi)存(指堆中內(nèi)存)了牺氨,直接可以把實(shí)際的值保存到指針中狡耻,而無需再去訪問堆中的數(shù)據(jù)。這無疑提高的內(nèi)存訪問速度和整體運(yùn)算速度猴凹。也就是說Tagged Pointer本身就可以表示一個NSNumber了夷狰。

那么如果一個數(shù)超過了Tagged Pointer所能表示的范圍,系統(tǒng)會怎么處理郊霎?看看這段代碼:

NSNumber*numberBig=@(0x2233567890ABCDEF);
NSLog(@"numberBig pointer is %p", numberBig);
在64位模擬器中運(yùn)行后沼头,我得到了如下結(jié)果:
代碼 objc:
numberBig pointer is 0x1394026a0

numberBig指針最后4位都是0,應(yīng)該是分配在堆中的對象书劝。因此瘫证,如果NSNumber超出了Tagged Pointer所能表示的范圍,系統(tǒng)會自動采用分配成對象庄撮,可以根據(jù)指針的最后4位是否為0來區(qū)分背捌。

isa指針優(yōu)化

查看NSObject類的頭文件,你會發(fā)現(xiàn)這段定義:

@interface NSObject: <NSObject>
 { 
  Class isa;
 }

所有類都繼承自NSObject洞斯,因此每個對象都有一個isa指針指向它所屬的類毡庆。在《ARM64 and You》文章中指出:在32位環(huán)境下,對象的引用計數(shù)都保存在一個外部的表中烙如,而對引用計數(shù)的增減操作都要先鎖定這個表么抗,操作完成后才解鎖。這個效率是非常慢的亚铁。而在64位環(huán)境下蝇刀,isa也是64位,實(shí)際作為指針部分只用到的其中33位徘溢,剩余的部分會運(yùn)用到Tagged Pointer的概念吞琐,其中19位將保存對象的引用計數(shù),這樣對引用計數(shù)的操作只需要原子的修改這個指針即可然爆,如果引用計數(shù)超出19位站粟,才會將引用計數(shù)保存到外部表,而這種情況往往是很少的曾雕,因此效率將會大大提高奴烙。

在WWDC2013的《Session 404 Advanced in Objective-C》視頻中,看到蘋果對于Tagged Pointer特點(diǎn)的介紹:

1.Tagged Pointer專門用來存儲小的對象,例如NSNumber和NSDate
2.Tagged Pointer指針的值不再是地址了切诀,而是真正的值揩环。
實(shí)際上它不再是一個對象了,它只是一個披著對象皮的普通變量而已幅虑。
它的內(nèi)存并不存儲在堆中检盼,也不需要malloc和free。
3.在內(nèi)存讀取上有著3倍的效率翘单,創(chuàng)建時比以前快106倍。

蘋果引入Tagged Pointer蹦渣,不但減少了64位機(jī)器下程序的內(nèi)存占用哄芜,還提高了運(yùn)行效率。完美地解決了小內(nèi)存對象在存儲和訪問效率上的問題柬唯。

Tagged Pointer的引入也帶來了問題认臊,即Tagged Pointer
因為并不是真正的對象,而是一個偽對象锄奢,所以你如果完全把它當(dāng)成對象來使失晴,可能會讓它露馬腳。所有對象都有 isa指針拘央,而Tagged Pointer其實(shí)是沒有的涂屁,因為它不是真正的對象。 因為不是真正的對象灰伟,所以如果你直接訪問Tagged Pointer的isa成員的話拆又,在編譯時將會有警告。

總之:

蘋果將Tagged Pointer引入栏账,給64位系統(tǒng)帶來了內(nèi)存的節(jié)省和運(yùn)行效率的提高帖族。Tagged Pointer通過在其最后一個bit位設(shè)置一個特殊標(biāo)記,用于將數(shù)據(jù)直接保存在指針本身中挡爵。Tagged Pointer并不是真正的對象竖般,使用時需要注意不要直接訪問其isa變量。

引用是為了加強(qiáng)記憶和方便回顧茶鹃,原文鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涣雕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子闭翩,更是在濱河造成了極大的恐慌胞谭,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件男杈,死亡現(xiàn)場離奇詭異丈屹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門旺垒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彩库,“玉大人,你說我怎么就攤上這事先蒋『眨” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵竞漾,是天一觀的道長眯搭。 經(jīng)常有香客問我,道長业岁,這世上最難降的妖魔是什么鳞仙? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮笔时,結(jié)果婚禮上棍好,老公的妹妹穿的比我還像新娘。我一直安慰自己允耿,他們只是感情好借笙,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著较锡,像睡著了一般业稼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蚂蕴,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天盼忌,我揣著相機(jī)與錄音,去河邊找鬼掂墓。 笑死谦纱,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的君编。 我是一名探鬼主播跨嘉,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吃嘿!你這毒婦竟也來了祠乃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤兑燥,失蹤者是張志新(化名)和其女友劉穎亮瓷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體降瞳,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘱支,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年蚓胸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片除师。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡小压,死狀恐怖鳖悠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情背零,我是刑警寧澤煮嫌,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布浑侥,位于F島的核電站枪向,受9級特大地震影響谷羞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜痕貌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一风罩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧芯侥,春花似錦、人聲如沸乳讥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽云石。三九已至唉工,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間汹忠,已是汗流浹背淋硝。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宽菜,地道東北人谣膳。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像铅乡,于是被迫代替她去往敵國和親继谚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險厭惡者阵幸,不喜歡去冒險花履,但是人生放棄了冒險,也就放棄了無數(shù)的可能挚赊。 ...
    yichen大刀閱讀 6,056評論 0 4
  • 公元:2019年11月28日19時42分農(nóng)歷:二零一九年 十一月 初三日 戌時干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 6,886評論 0 2
  • 今天上午陪老媽看病诡壁,下午健身房跑步,晚上想想今天還沒有斷舍離荠割,馬上做妹卿,衣架和旁邊的的布衣架,一看亂亂,又想想自己是...
    影子3623253閱讀 2,915評論 1 8