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去查找就可以了,就可以找到这个方法了。