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


指针 和 一个联合体来完成数据的存储。通过观察也只是对结构进行了一些优化,其他思路还是不变的。前提不变:使用lldb调试的前提是你需要有lib-objc的源码环境
buckets()函数来进行lldb调试,和老版本并没有区别,有兴趣的可以通过最上方的链接去之前的文中看看。前提: 模拟器环境
本文的重头戏,脱离源码来进行调试和测试。
//模拟器
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;
};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);
}
}

FULL_UTILIZATION_CACHE_SIZE= 1 << 3 = 8为小缓存区。应该是考虑到小缓存区时hash冲突不会造成太大性能损耗。容量可以在4或者8的情况下全部放满。 只有真机的情况下才生效