一个 NSObject 对象占用多少内存空间?
在64
位CPU中,NSObject 对象占用大小为16字节,其中8字节为指针大小,8字节为实例对象结构体所占大小。
在32
位CPU中,NSObject 对象占用大小为8字节,其中4字节为指针大小,4字节为实例对象结构体所占大小。
可以参考唐巧的 深入理解Tagged Pointer
故所以当4个字节就能表示的值,要用8个字节来存储时,就会很浪费内存,所以苹果引用了tagged pointer
的概念,注意是在64位系统中!
NSTagged Pointer
NSNumber
在object_msgSend
的汇编代码中,我们常常会看到tagged point类型的判断,如下段代码
END_ENTRY _objc_msgSend
ENTRY _objc_msgLookup
UNWIND _objc_msgLookup, NoFrame
cmp x0, #0 // nil check and tagged pointer check
b.le LLookup_NilOrTagged // (MSB tagged pointer looks negative)
ldr x13, [x0] // x13 = isa
and x16, x13, #ISA_MASK // x16 = class
LLookup_GetIsaDone:
CacheLookup LOOKUP // returns imp
LLookup_NilOrTagged:
b.eq LLookup_Nil // nil check
// tagged
mov x10, #0xf000000000000000
cmp x0, x10
b.hs LLookup_ExtTag
adrp x10, _objc_debug_taggedpointer_classes@PAGE
add x10, x10, _objc_debug_taggedpointer_classes@PAGEOFF
ubfx x11, x0, #60, #4
ldr x16, [x10, x11, LSL #3]
b LLookup_GetIsaDone
LLookup_ExtTag:
adrp x10, _objc_debug_taggedpointer_ext_classes@PAGE
add x10, x10, _objc_debug_taggedpointer_ext_classes@PAGEOFF
ubfx x11, x0, #52, #8
ldr x16, [x10, x11, LSL #3]
b LLookup_GetIsaDone
当我们存储一个NSNumber
时,我们一般想的是通过指针取到地址,通过地址读取内存中的数据,这默认的需要创建一块内存,还有一个指针。然后,对象在内存中是对齐的,它们的地址总是指针大小的整数倍,通常为16
的倍数。对象指针是一个64位的整数,而为了对齐,一些位将永远是零。
Tagged Pointer
利用了这一现状,它使对象指针中非零位有了特殊的含义。在苹