Tagged Pointer 介紹
蘋果對于Tagged Pointer特點的介紹:
Tagged Pointer主要解決內(nèi)存浪費和訪問效率的問題
-
Tagged Pointer
專門用來存儲小的對象涧尿,NSString
向族、NSNumber
、NSDate
抖苦、NSIndexPath
-
Tagged Pointer
指針的值不再是地址了,而是真正的值炎咖。所以练对,實際上它不再是一個對象了,它只是一個披著對象皮的普通變量而已兔簇。所以发绢,它的內(nèi)存并不存儲在堆中,也不需要malloc和free垄琐。 - 在內(nèi)存讀取上有著3倍的效率边酒,創(chuàng)建時比以前快106倍 銷毀速度更快
如果想深入了解
如果你想要更進一步,去挖掘 Tagged Pointer 是如何實現(xiàn)的狸窘,可以參考 Friday Q&A 2012-07-27: Let’s Build Tagged Pointers 和 objc 源碼墩朦。
為什么要引入Tagged Pointer
iPhone5s 采用64位處理器。
對于64位程序翻擒,我們的數(shù)據(jù)類型的長度是跟CPU的長度有關(guān)的氓涣。
image.png
這樣就導(dǎo)致了 一些對象占用的內(nèi)存會翻倍。
同時 維護程序中的對象需要 分配內(nèi)存陋气,維護引用計數(shù)劳吠,管理生命周期,使用對象給程序的運行增加了負(fù)擔(dān)巩趁。
Tagged Pointer
未引入 Tagged Pointer
image.png
引入 Tagged Pointer
image.png
判斷是否是 Tagged Pointer
image.png
可以從 objc 源碼中找出支持 Tagged Pointer 的對象類型痒玩,如下:
typedef uint16_t objc_tag_index_t;
enum
{
OBJC_TAG_NSString = 2,
OBJC_TAG_NSNumber = 3,
OBJC_TAG_NSIndexPath = 4,
OBJC_TAG_NSDate = 6,
....
};
即針對 NSString、NSNumber议慰、NSDate蠢古、NSIndexPath 這些類型,都支持 Tagged Pointer 技術(shù)别凹。
我們通過 NSNumber 以及 NSString 對象來觀察 Tag+Data 的存儲形式
NSNumber *number1 = @1; //0xa061a1f0f2864c7a
NSNumber *number2 = @2; //0xa061a1f0f2864c4a
NSNumber *number3 = @(0xFFFFFFFFFFFFFFF); //0x600003eac120
NSNumber *number4 = @(1.2); //0x600003eac1c0
int num4 = 5;
NSNumber *number5 = @(num4); //0xa061a1f0f2864c3a
long num5 = 6;
NSNumber *number6 = @(num5); //0xa061a1f0f2864c0b
float num6 = 7;
NSNumber *number7 = @(num6); //0xa061a1f0f2864c1c
double num7 = 8;
NSNumber *number8 = @(num7); //0xa061a1f0f2864ced
//值: 0xa061a1f0f2864c7a 0xa061a1f0f2864c4a 0x600003eac120 0x600003eac1c0 0xa061a1f0f2864c3a 0xa061a1f0f2864c0b 0xa061a1f0f2864c1c 0xa061a1f0f2864ced
NSLog(@"%p %p %p %p %p %p %p %p", number1, number2, number3, number4, number5, number6, number7, number8);
由上表我們得出:
- 很大的數(shù)字草讶,超過 Tagged Pointer 表示上限的時候,將會轉(zhuǎn)為對象存儲炉菲,存放在堆上堕战;
- 如果是含有小數(shù)點的浮點數(shù)坤溃,將會直接以對象方式存儲;
-
其余類型的數(shù)字嘱丢,包括不含小數(shù)部分的浮點型和整型都會以 Tagged Pointer 存儲浇雹。
并且,針對以上部分屿讽,我們整理出 Tagged Pointer 的存儲格式如下昭灵,以 number1 為
image.png
NSString
同上面 NSNumber
的處理邏輯,NSString
處理的類似伐谈。
NSString *str1 = @"a"; //0x1049cc248
NSString *str2 = [NSString stringWithFormat:@"a"]; //0xa000000000000611
NSString *str3 = [NSString stringWithFormat:@"bccd"]; //0xa000000646363624
NSString *str4 = [NSString stringWithFormat:@"c"]; //0xa000000000000631
NSString *str5 = [NSString stringWithFormat:@"cdasjkfsdljfiwejdsjdlajfl"];//0x1c02418f0
NSLog(@"%@ %@ %@ %@ %@",
[str1 class], //__NSCFConstantString
[str2 class], //NSTaggedPointerString
[str3 class], //NSTaggedPointerString
[str4 class], //NSTaggedPointerString
[str5 class]); // __NSCFString
根據(jù)以上結(jié)果烂完,我們將 NSString 分類三類:
- 常量類型:__NSCFConstantString,定義的字符串常量诵棵。
- Tagged Pointer 類型:NSTaggedPointerString抠蚣,通過對象方法創(chuàng)建的短字符串。
- NSString 對象類型:__NSCFString履澳,包括 NSString嘶窄、NSMutableString 等創(chuàng)建的字符串對象。
以上距贷,整理如下:
NSString 以 Tagged Pointer 的存儲格式如下:
2.3 內(nèi)存管理
三柄冲、一個面試問題的研究
該面試題如下: