美文网首页
cache_t的浅析学习

cache_t的浅析学习

作者: 竹屋听雨 | 来源:发表于2019-12-25 19:25 被阅读0次

cache_t的一浅析学习

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

    class_rw_t *data() { 
        return bits.data();
    }
看一下结构 结构体类型
struct cache_t {
    struct bucket_t *_buckets; // 8
    mask_t _mask;  // 4
    mask_t _occupied; // 4
// -----方法
public:
    struct bucket_t *buckets();
    mask_t mask();
    mask_t occupied();
    void incrementOccupied();
    void setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask);
    void initializeToEmpty();

    mask_t capacity();
    bool isConstantEmptyCache();
    bool canBeFreed();

    static size_t bytesForCapacity(uint32_t cap);
    static struct bucket_t * endMarker(struct bucket_t *b, uint32_t cap);

    void expand();
    void reallocate(mask_t oldCapacity, mask_t newCapacity);
    struct bucket_t * find(cache_key_t key, id receiver);

    static void bad_cache(id receiver, SEL sel, Class isa) __attribute__((noreturn));
};

//bucket_t 存储方法的 imp key;
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__
    MethodCacheIMP _imp;
    cache_key_t _key;
#else
    cache_key_t _key;
    MethodCacheIMP _imp;
#endif

public:
    inline cache_key_t key() const { return _key; }
    inline IMP imp() const { return (IMP)_imp; }
    inline void setKey(cache_key_t newKey) { _key = newKey; }
    inline void setImp(IMP newImp) { _imp = newImp; }

    void set(cache_key_t newKey, IMP newImp);
};


 
//缓存填充
static void cache_fill_nolock(Class cls, SEL sel, IMP imp, id receiver)
{
    cacheUpdateLock.assertLocked();

    // Never cache before +initialize is done
    // 判断当前的cache是否初始化成功
    if (!cls->isInitialized()) return;

    // Make sure the entry wasn't added to the cache by some other thread 
    // before we grabbed the cacheUpdateLock.
    // 判断当前缓存里面是否已经存在 传入的cls,sel
    if (cache_getImp(cls, sel)) return;
    // 需要缓存 进入下面的流程 cls --> cache sel --> key
    //
    cache_t *cache = getCache(cls);
    // 把sel 方法名 进行符号化 方便存储
    cache_key_t key = getKey(sel);

    // Use the cache as-is if it is less than 3/4 full
    // newOccupied: 新建一个占用, 告诉缓存 我要占用加1; 用来缓存新的方法
    mask_t newOccupied = cache->occupied() + 1;
    // 读取缓存的容量
    mask_t capacity = cache->capacity();
    /**
     如果缓存容量超过 3/4 就要进行扩容;
     */
    if (cache->isConstantEmptyCache()) {
        // Cache is read-only. Replace it.cache 是只度的,所以要进行重置 ↓⤵️
        cache->reallocate(capacity, capacity ?: INIT_CACHE_SIZE);
    }
    else if (newOccupied <= capacity / 4 * 3) {
        // Cache is less than 3/4 full. Use it as-is.
    }
    else {
        // Cache is too full. Expand it.扩容
        cache->expand();
    }

    // Scan for the first unused slot and insert there.
    // There is guaranteed to be an empty slot because the 
   // minimum size is 4 and we resized at 3/4 full.
   // 通过key 去查找bucket  ⤵️⤵️调用cache-> find 方法 
   // 找到bucket 之后调用set 进行key,imp的一个绑定;
    bucket_t *bucket = cache->find(key, receiver);
    if (bucket->key() == 0) cache->incrementOccupied();
    bucket->set(key, imp);
}
#Mark : ↑⬆️ 当前cache是空的话 进行一步创建调用 reallocate方法
void cache_t::reallocate(mask_t oldCapacity, mask_t newCapacity)
{
    bool freeOld = canBeFreed();
    // 获取旧的 buckets
    bucket_t *oldBuckets = buckets();
    // 创建新的 buckets
    bucket_t *newBuckets = allocateBuckets(newCapacity);

    // Cache's old contents are not propagated. 
    // This is thought to save cache memory at the cost of extra cache fills.
    // fixme re-measure this

    assert(newCapacity > 0);
    assert((uintptr_t)(mask_t)(newCapacity-1) == newCapacity-1);
//    设置buckets mask
    setBucketsAndMask(newBuckets, newCapacity - 1);
//    释放旧的buckets 的内存
    if (freeOld) {
        cache_collect_free(oldBuckets, oldCapacity);
        cache_collect(false);
    }
}
#Mark:cache->find 方法查找bucket

bucket_t * cache_t::find(cache_key_t k, id receiver)
{
    assert(k != 0);

    bucket_t *b = buckets();
    mask_t m = mask();
// 通过cache_hash函数 begin[k,m]计算key值k 对应的一个index的begin值,用来记录查询的起始索引
    mask_t begin = cache_hash(k, m);
//   将begin赋值给i,用于切换索引值
    mask_t i = begin;
    do {
/**
 用这个i从散列表取值,如果取出来的bucket_t的key=k,则查询成功,返回bucket_t,
 如果key=0,说明索引i的位置上还没有缓存过方法,同样需要返回当前的bucket_t,用于终止缓存查询。
 */
        if (b[i].key() == 0  ||  b[i].key() == k) {
            
            return &b[i];//返回的是地址;
        }
    } while ((i = cache_next(i, m)) != begin);
//这一步相当于i=i-1,回到上面的do循环里面,相当于查找散列表上一个单元格里面的元素,再次进行key值k的比较。
    // hack
    Class cls = (Class)((uintptr_t)this - offsetof(objc_class, cache));
    cache_t::bad_cache(receiver, (SEL)k, cls);
}


#Mark: 当前的扩容算法
void cache_t::expand()
{
    cacheUpdateLock.assertLocked();
    
    uint32_t oldCapacity = capacity();
    uint32_t newCapacity = oldCapacity ? oldCapacity*2 : INIT_CACHE_SIZE;

    if ((uint32_t)(mask_t)newCapacity != newCapacity) {
        // mask overflow - can't grow further
        // fixme this wastes one bit of mask
        newCapacity = oldCapacity;
    }

    reallocate(oldCapacity, newCapacity);
}

cache_t流程分析.png

最近原则

相关文章

  • cache_t的浅析学习

    cache_t的一浅析学习 最近原则

  • cache_t分析

    cache_t分析 cache_t的作用:用于快速查找方法 cache_t的特点:是可增量扩展的hash表结构ha...

  • objc_class中的cache_t分析

    本文探索的的主要是两点 1、cache_t的结构 2、cache_t里存储的哪些 cache_t结构分析 打开源码...

  • 七、cache_t 分析

    主要内容:cache_t的底层原理:分析cache_t缓存的内家及怎样缓存的。一、分析cache_t主要存储的是什...

  • cache_t原理分析

    类结构中的cache_t: cache_t的结构体:bucketsMask 、_mask_unused、_flag...

  • 类(三)-- cache_t分析

    类(一)-- 底层探索类(二)-- method归属类(三)-- cache_t分析 cache_t作用 用来缓存...

  • 方法缓存Cache_t分析

    缓存Cache_t bucket_t cache_t 缓存的是 方法 method_t: 缓存流程 缓存的入口是:...

  • iOS cache_t结构分析

    cache_t源码结构精简后的cache_t源码如下: 可以看到有个重要的函数void incrementOccu...

  • OC类底层结构-方法缓存之cache_t

    什么是cache_t cache_t是负责OC类中的结构体objc_class[https://www.jians...

  • 探索Cache_t

    Cache_t 的整体分析 Cache_t的源码 在objc/objc-runtime-new源码下查找结构体ca...

网友评论

      本文标题:cache_t的浅析学习

      本文链接:https://www.haomeiwen.com/subject/dzucoctx.html