OC底层探索13-基于objc4-818的cache_t结构探索OC底层探索13-基于objc4-818的cache_t结构探索

2021-08-09 11:17:30 浏览数 (1)

在OC底层探索09-cache_t实现原理探索中已经对cache缓存的机制做了介绍,但是这文章是基于objc4-781来探索的。技术更新的太快了,在objc4-818中cache_t的结构又发生了很大的变化。与此同时缓存的过程中也有一些小的优化。

objc4-781中的cache_t结构

objc4-818中的cache_t结构

  • 通过一个指针 和 一个联合体来完成数据的存储。通过观察也只是对结构进行了一些优化,其他思路还是不变的。
  • 通过结构的变化,来兼容不同架构下的数据存储结构。相信一定是为了适应越来越多的架构。

使用lldb来调试cache

前提不变:使用lldb调试的前提是你需要有lib-objc的源码环境

  • 发现通过buckets()函数来进行lldb调试,和老版本并没有区别,有兴趣的可以通过最上方的链接去之前的文中看看。

1. 脱离源码来调试cache(模拟器)

前提: 模拟器环境

本文的重头戏,脱离源码来进行调试和测试。

代码语言:javascript复制
//模拟器
typedef uint32_t mask_t;

struct HR_bucket_t {
    SEL sel;
    IMP imp;
};

struct HR_cache_t {
    uintptr_t _bucketsAndMaybeMask;
    union {
        struct {
            mask_t    _maybeMask;
            uint16_t                   _flags;
            uint16_t                   _occupied;
        };
    };
    
    //该方法是模仿源码
    static constexpr uintptr_t bucketsMask = ~0ul;
    struct HR_bucket_t* buckets() const
    {
        return (HR_bucket_t *)(_bucketsAndMaybeMask & bucketsMask);
    }
};

struct HR_class_data_bits_t {
    uintptr_t bits;
};

struct HR_objc_class {
    Class ISA;
    Class superclass;
    struct HR_cache_t cache;             // formerly cache pointer and vtable
    struct HR_class_data_bits_t bits;
};
调用
代码语言:javascript复制
int main() {
    HRTest * t = [HRTest alloc];
    
    struct HR_objc_class *obj = (__bridge struct HR_objc_class *)(HRTest.class);
        
    NSLog(@"mask:%u---occupied:%u",obj->cache._maybeMask,obj->cache._occupied);

    for (mask_t i = 0; i < obj->cache._maybeMask; i  ) {
        struct HR_bucket_t bucket = obj->cache.buckets()[i];
        NSLog(@"sel:%@---imp:%p",NSStringFromSelector(bucket.sel),bucket.imp);
    }
}
查看结果
  • 在模拟下的结果和旧版本是一致的。

2. 缓存过程中的一些优化

  • 定义FULL_UTILIZATION_CACHE_SIZE= 1 << 3 = 8小缓存区。应该是考虑到小缓存区时hash冲突不会造成太大性能损耗。
  • 多了这部分逻辑,相比于旧逻辑容量可以在4或者8的情况下全部放满。
  • 只有真机的情况下才生效

0 人点赞