iOS相关技术原理

iOS objc_class 中的 cache__t 结构

2020-02-09  本文已影响0人  孙掌门

iOS objc_class 中的 cache__t 结构

我们来看下源码的底层定义

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags

cache_t cache; 其实是方法缓存,使用散列表来缓存曾经调用过得方法,可以提高方法的查找速度。

我之前提到过,方法查找其实就是通过 isa 指针去找,当我们调用一个类的实例方法的时候,首先会通过 isa 指针去自己的类对象中查找,去类对象中的 method_list_t 中去查找,如果没有查找到,再通过superClass指针,找到自己的父类对象,然后去自己的父类对象中去查找,这样一直进行下去,比如我们重复调用一个方法,那么每次都这样去查找,肯定是相对比较耗性能的,这时候就是 cache_t 的作用,当我们调用过这个方法之后,系统就会把这个方法方法 cache 里面,当我们下次调用方法的时候,就会优先在当前的类对象的 cache 当中去查找,如果找到了,就不需要在遍历查找了,优化了效率。

cache_t

struct cache_t {
    struct bucket_t *_buckets;
    mask_t _mask;
    mask_t _occupied;

其中 _buckets 就是存放着我们的方法,也就是散列表,_mask 是散列表的长度减1,如果 _buckets 的长度为2,那么 mask 久违1,_occupied 表示已经缓存的方法的数量

bucket_t

struct bucket_t {
private:
    // IMP-first is better for arm64e ptrauth and no worse for arm64.
    // SEL-first is better for armv7* and i386 and x86_64.
#if __arm64__
    uintptr_t _imp;
    SEL _sel;
#else
    SEL _sel;
    uintptr_t _imp;
#endif


可以看到这个结构体的 存放着一个 sel ,当做 key 来存储,imp 就是这个函数的地址值,

总结

比如当我们现在调用一个 -(void)test; 方法,那么会把我们的这个方法,放到我们的当前的类对象的 cache_t 结构体中,存在在 _buckets 这个额里面,其中 bucket_t 是一个结构体,我们的这个方法,会变成这个结构体放在_buckets当中,把当前方法的 sel 当做key,也就是 @selector(test) 当做key,他的函数地址,也就是 imp 当做 value 来存放,下次直接来 _buckets去查找就可以了,就可以找到这个方法了。

上一篇 下一篇

猜你喜欢

热点阅读