当前位置: 首页>编程语言>正文

方法缓存Cache_t分析

缓存Cache_t

struct cache_t { // 16
    struct bucket_t *_buckets; // 8
    mask_t _mask; // 4
    mask_t _occupied; // 4
    ...

bucket_t

struct bucket_t {
#if __arm64__
    MethodCacheIMP _imp;
    cache_key_t _key;
#else
    cache_key_t _key;
    MethodCacheIMP _imp;
#endif
...
}

cache_t 缓存的是 方法 method_t

struct method_t {
    SEL name;
    const char *type;
    MethodListIMP imp;
}

缓存流程

缓存的入口是:cache_fill_nolock函数

方法缓存Cache_t分析,第1张
cache_fill_nolock函数.png

1、首先我们从缓存的入口开始分析,一进入到cache_fill_nolock函数,先查找现有的缓存中是否有对应的方法,有就返回,没有就继续往下走,其中通过sel创建一个key cache_key_t key = getKey(sel);
2、判断现有的缓存是不是空缓存,
如果条件为true,就去创建一个新的buckets桶子,把_mask = newMask; _occupied = 0;,如下:

cache->reallocate(capacity,capacity ? : INIT_CACHE_SIZE);

通过cache->find(key, receiver) 找到刚创建的 buckets,再将新的方法存放进去bucket->set(key, imp);

在cache->find(key, receiver)函数中,是怎么找到缓存bucket_t的呢?
首先通过cache_hash函数计算出key值对应的index值 begin,然后根据这些索引找到bucket_t,如果遍历完后都没有找到的话,说明查找失败,那就会调用bad_cache方法,如下图:

方法缓存Cache_t分析,第2张
cache->find函数.png

如果缓存里的存储大小 小于 开辟占用的3/4,不作任何处理仅需往下走;
如果缓存里的存储大小 大于 开辟占用的3/4,就需要进行扩容了。

//开始扩容
cache->expend();
方法缓存Cache_t分析,第3张
扩容.png

扩容是按照原来的2倍来进行的,扩容后,又和之前一样重新创建一个新的buckets。
接着继续查找这个刚创建的buckets,将方法放进buckets中去。

在重新创建一个新的buckets时,会将原来的方法缓存清空掉。如果不清空内存的话,以后如果方法缓存的多了,对应的查找速度也会有一定的影响,内存平移也是一个麻烦。

方法缓存Cache_t分析,第4张
屏幕快照 2020-08-20 下午5.41.43.png

https://www.xamrdz.com/lan/5zu1848850.html

相关文章: