iOS 对象所需内存和系统实际开辟内存详解

开始探索

新建People类 任何属性都不加

@interface People : NSObject

@end

创建对象

People *p = [[People alloc]init];
NSLog(@"---class_getInstanceSize--%ld",class_getInstanceSize(p.class));// 8
这个时候是因为每个类或者类对象都有一个isa指针

增加一个属性

@interface People : NSObject
@property(nonatomic,assign)int age;
@end

再次打印大小

People *p = [[People alloc]init];
NSLog(@"---class_getInstanceSize--%ld",class_getInstanceSize(p.class));// 16

理论上讲我们增加了一个int 类型的age 应该增加4个字节 打印出来的大小应该是12 但为什么是16 ?看runtime中的代码

OC的对齐函数
uint32_t alignedInstanceSize() {
        return word_align(unalignedInstanceSize());
    }
    size_t instanceSize(size_t extraBytes) {
        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;
        return size;
    }
    static inline uint32_t word_align(uint32_t x) {
    return (x + WORD_MASK) & ~WORD_MASK;
}

主要来看 (x + WORD_MASK) & ~WORD_MASK; 这个结果 把宏定义转过来就是 (x+7)& ~7 就拿刚才的结果举例就变成了
(12+7) & ~7转成二进制就是
(00001100 + 00000111) & 11111000
就转成 00010011 & 11111000
结果就是 00010000 就是 16,

再来看class_getInstanceSize

size_t class_getInstanceSize(Class cls)
{
    if (!cls) return 0;
    return cls->alignedInstanceSize();
}
小结

此时可以看出以属性来计算大小的时候是以8字节对齐的 而class_getInstanceSize拿到的就是以8字节对齐的内存大小

在来看malloc_size

看看实际上系统分配的内存大小 修改People类

@interface People : NSObject

@property(nonatomic,assign)int age;
@property(nonatomic,copy)NSString *name;
@end

按照上面的规则 8+4+8 class_getInstanceSize应该是 24 8字节对齐
那么malloc_size 是多少

People *p = [[People alloc]init];
NSLog(@"---class_getInstanceSize--%ld",class_getInstanceSize(p.class));// 24
 NSLog(@"---class_getInstanceSize--%ld",malloc_size(CFBridgingRetain(p))); // 32

惊奇的发现malloc_size 是 32。看来苹果在开辟内存的时候还有内存对齐 主要来看下面这个算法

k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM; // round up and shift for number of quanta
	slot_bytes = k << SHIFT_NANO_QUANTUM;		

把宏定义替换进去就是 
k = (size + 16-1)>>4
slot_bytes = k << 4

比如 刚才的 20 按照这个算法之后就是
k=(00010100 + 00001111) >>4
k= 00100011 >> 4
k= 00000010
slot_bytes = 00000010<<4
slot_bytes = 00100000 = 32

小结

其实结论就是 实际分配内存是按照16字节对齐的 内存大小都是16 的倍数。

编译器优化

举例来讲就是 一个1字节的和一个4字节的会被放在一个内存段里节省内存 不用再出现1个字节补7个字节来对齐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值