美文网首页
iOS-底层 对象内存对齐

iOS-底层 对象内存对齐

作者: 陪妮走未来 | 来源:发表于2020-10-06 09:53 被阅读0次

    什么是内存对齐?

    内存对齐,简单来说就是编译器为了节省查找内存时间,通过一定的算法将数据按照规律存储,而不是一个一个的紧密排列,每个平台上的编译器都有自己的“对齐系数”(一般为4和8),而iOS的对齐系数为8即8字节对齐

    内存对齐的好处

    CPU存取原理
    CPU把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的。每次内存存取都会产生一个固定的开销,减少内存存取次数将提升程序的性能。所以 CPU 一般会以 2/4/8/16/32 字节为单位来进行存取操作。我们将上述这些存取单位也就是块大小称为(memory access granularity)内存存取粒度。

    所以在读取对齐的内存效率更高,在读取未对齐的内存时,CPU需要做两次访问,而读取对齐的内存只需要访问一次,这大大提升了CPU的效率,提升了性能。

    内存对齐规则:

    【规则一】数据成员的对齐规则可以理解为min(m, n) 的公式, 其中 m表示当前成员的开始位置, n表示当前成员所需要的
    位数。如果满足条件 m 整除 n (即 m % n == 0), n 从 m 位置开始存储, 反之继续检查 m+1位置 能否整除 所需的位数
    n, 直到可以整除, 从而就确定了当前成员的开始位置。

    【规则二】数据成员为结构体:当结构体嵌套了结构体时,作为数据成员的结构体的自身长度作为外部结构体的最大成.
    员的内存大小,比如结构体a嵌套结构体b,b中有char、int、double等,则b的自身长度为8

    【规则三】最后结构体的内存大小必须是结构体中最大成员内存大小的整数倍,不足的需要补齐。

    常见数据类型所占内存大小的表:

    image

    iOS获取内存大小的三种方式

    sizeof: 是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数。在编译阶段 就会确定大小
    class_getInstanceSize: 这个方法由runtime提供api,用于获取实例对象所占的内存大小,本质是获取实例对象中成员变量的内存大小
    (注:如自定义类或继承关系 属性的多少变化而变化,如单纯的继承NSObject并且没有任何属性 打印为8 因为 有隐藏 isa 万物皆对象,而对象的本质为 继承 objc_object 的结构体 它就是对象模板)

    malloc_size: 获取系统实际分配的内存大小(16字节对齐)
    拓: 我们知道alloc 流程 最重要的三部曲
    cls->instanceSize:计算需要开辟的内存空间大小(这里有一个算法为16字节对齐)
    calloc:申请内存,返回地址指针
    obj->initInstanceIsa:将 类 与 isa 关联

    下面以一段代码为例

    int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSObject *object = [[NSObject alloc]init];
        NSLog(@"%lu - %lu - %lu",sizeof(object),class_getInstanceSize([NSObject class]),malloc_size((__bridge const void *)(object)));
    
    }
    return 0;
    
    

    }
    运行后的输出为:8 - 8 - 16

    解释:
    sizeof:可用于获取类、结构、共用体和其他用户自定义数据类型的大小。
    class_getInstanceSize:返回类实例的大小。
    malloc_size:返回实际给定的内存大小

    结构体内存对齐

    接下来,我们首先定义两个结构体,分别计算他们的内存大小,以此来引入今天的正题:内存对齐原理

    //1、定义两个结构体
    struct Struct1{
        char a;     //1字节
        double b;   //8字节
        int c;      //4字节
        short d;    //2字节
    }Struct1;
    
    struct Struct2{
        double a;   //8字节
        int b;      //4字节
        short c;    //2字节
        char d;     //1字节
    }Struct2;
    
    //计算 结构体占用的内存大小
    NSLog(@"%lu-%lu",sizeof(Struct1),sizeof(Struct2));
    
    

    以下是输出结果

    image

    从打印结果我们可以看出一个问题,两个结构体除了变量顺序一样之外,其他几乎完全一致,那么他们的大小为什么内存大小不相等呢?这就是内存对齐现象。

    相关文章

      网友评论

          本文标题:iOS-底层 对象内存对齐

          本文链接:https://www.haomeiwen.com/subject/hnzzuktx.html