iOS 方法缓存机制cache_t

类对象的数据结构

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // 方法缓存
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
};

struct objc_object {
private:
    isa_t isa;
};
其中cache_t就是方法缓存,用散列表缓存曾今调用过的方法
struct cache_t {
  struct bucket_t *_buckets;// 散列表
  mask_t _mask;// 散列表长度 -1
  mask_t _occupied;// 已缓存的方法数量
};

struct bucket_t {
  cache_key_t _key;// SEL作为Key
  IMP _imp;// 函数内存地址
};

缓存查找方法在:源码的objc-cache.mm文件中

struct bucket_t *_bucket;是一个散列表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个索引位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

索引位置 bucket_t
0 Null
1 Null
2 bucket_t(_key = @selector(func1), _imp)
3 bucket_t(_key = @selector(func2), _imp)
... ......

SEL & _mask = 索引位置,再通过索引位置找到bucket_t,其中SEL为Key,最终找到的bucket_t为Value,计算索引位置的函数f(SEL) = SEL & _mask;被称为散列函数(也叫哈希函数)。

  • 在缓存方法的时候,通过散列函数和关键码值计算出一个索引位置,并把value放入散列表对应的索引位置处,其他还没有存放的位置全部初始化为Null;如果发现计算的索引位置已经存放了value,那么就根据自定义的规则把value存储到其他索引位置对应的value中。
  • 值得注意的是,_mask关键码值是变化的,如果当前的散列表已经存放满的时候,_mask值会扩大,同时清空原来的散列表,重新进行缓存。

你可能感兴趣的:(iOS 方法缓存机制cache_t)