NSObject底层探索-cache_t

169 阅读1分钟

问题/目标分析

分析NSObject 底层数据 cache_t 信息

方法分析

通过源码,lldb x/4xg 命令,打印内存中cache_t信息

实验步骤

1、打印cache_t中 bucket_t信息
执行walk 方法之前。

执行walk 方法一次。
执行walk 方法多次。

使用类型强转直接打印内容


typedef uint32_t mask_t;
typedef uintptr_t cache_key_t;
typedef unsigned long  uintptr_t;

//注意mac和iphone的定义顺序不一样,根据机型更换顺序
struct lg_bucket_t {
    IMP _imp;
    cache_key_t _key;
};

struct lg_cache_t {
    struct lg_bucket_t *_buckets;
    mask_t _mask;
    mask_t _occupied;
};

struct lg_class_data_bits_t {
    uintptr_t bits;
};

struct lg_objc_class {
    Class ISA;
    Class superclass;
    struct lg_cache_t cache;             // formerly cache pointer and vtable
    struct lg_class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
};

+(void)testStruct
{
    LGPerson *person = [[LGPerson alloc] init];
           Class pClass = [LGPerson class];
           // cache_t 为什么没有 - 第一次
           [person sayHello];
           [person sayCode];
//           [person sayNB]; 

           struct lg_objc_class *lg_pClass = (__bridge struct lg_objc_class *)(pClass);
           for (mask_t i = 0; i<lg_pClass->cache._mask; i++) {
               struct lg_bucket_t bucket = lg_pClass->cache._buckets[i];
               NSLog(@"%lu - %p",bucket._key,bucket._imp);
           }
           NSLog(@"%@ - %p",person,pClass);
    
}

结果

可以在macoview中找到对应的方法

结果分析

cache_t是一个缓存方法的列表,从中可以找到近期运行的方法。
bucket 为 sel-imp对应字典
mask 为总缓存大小-1
occupied 为当前缓存区使用大小 当缓存区到达最大缓存的3/4时,清空缓存,缓存大小翻倍。

总结实验

从cache_t可以知道类型近期调用的方法,也是方法查找加速的一个工具,增加其大小可以增加缓存命中。