性能调优、测试iOS底层iOS Kit

类的内存结构优化

2021-06-24  本文已影响0人  冼同学

WWDC2020对runtime的优化

类的数据结构

《类的探究分析》一文中就详细地解读了类的结构。在APP编译成二进制文件中,类的数据结构发生了变化,其中包含了最常被访问的信息,指向元类、父类和方法缓存的指针。以下是类的数据结构图:

类的数据结构

Clean Memory 和 Dirty Memory的区别

Clean Memory

Clean Memory指的是在程序运行中不会发生改变的内存class_ro_t就是属于Clean Memory的,class_ro_t`内存图解:

class_ro_t数据结构

Dirty Memory

Dirty Memory指的是在程序运行中会发生改变的内存,也就是我们俗称的脏数据。类的结构一经使用就会变成Dirty Memory,因为运行时会向它写入新的数据。例如往类中添加方法又或者加载类的子类父类,这里指的是class_rw_t。class_rw_t内存图解如下:

class_rw_t数据结构

总结:

dirty memory要比clean memory更有价值而且要多,只要进行运行它就必须一直存在,通过分离出那些不会被改变的数据,可以把大部分的类数据存储为clean memory,这样才能不断的提高程序的性能。

class_rw_t 的优化

dirty memory在类第一次加载的时候就一直存在,runtime会为它分配额外的内存。运行时分配的存储容量时class_rw_t用于读取-编写数据,但是dirty memory中仍然存在着比较多的clean memory,为了提高空间的利用率,拆分出更多的clean memory,减少dirty memory容量是比奴可少的。
第一步:拆分出class_ro_t,即运行时不被修改的内存。如下图:

提取lass_ro_t
注意:由上图发现一个疑点,为什么方法,属性在class_ro_t中时,class_rw_t还要有方法,属性呢?

总结

成员变量/实例变量和属性的区别

《类的探究分析》一文中提到了成员变量存放在class_ ro_t中,那么我们用过查找objc4源码得出下图:

实例变量存放位置
代码层面探究:
@interface XXPerson : NSObject
{
    int hobby;                 //成员变量
    NSObject *objc;            //实例变量
}
@property (nonatomic,strong) NSString *name;                 //属性
@property (nonatomic,strong) NSString *nickName;
@property (nonatomic,assign) int age;
@end

通过xrun编译成main.cpp文件,查看底层代码:

补充

官方类型编码

官方类型编码

注意:

objc_setProperty与copy的关系

objc_setProperty方法相当于一个中间层方法,主要是避免了每个类都调用底层的objc_setProperty方法。当用copy关键字修饰属性时,该属性在编译时候setter方法就会从定向到objc_setProperty方法,不像其他属性·setter·方法使用首地址+内存偏移的方式找到方法实现。
示例代码:

@interface XJPerson : NSObject
@property (nonatomic,copy) NSString *name;         //注意每个属性的关键字
@property (nonatomic,strong) NSString *nickName;
@property (atomic,copy) NSString *address;
@property (atomic) NSString *school;
@end

编译之后查看main.cpp,得到下图:

main.cpp源码结果
结论:

LLVM验证对象属性为copy时,setter方法的访问

验证流程图:

LLVM验证流程图
LLVM源码流程:objc_setProperty -> getSetPropertyFn -> GetPropertySetFunction -> PropertyImplStrategy -> IsCopy(判断copy关键字)
结论:无论属性是否是原子性还是非原子性的,用到copy关键字修饰的属性setter方法底层都用objc_setProperty实现,strong关键字无法通过最后得判断,需要通过首地址+内存偏移的方式实现。

总结:

底层代码的分析需要很好的耐心,过程也是非常的枯燥。但是当你弄明白了原理之后,就会发现知识是环环相扣的。非常高兴自己又多了一分收获,加油!

上一篇下一篇

猜你喜欢

热点阅读