美文网首页
cache_t分析

cache_t分析

作者: CS_SDN | 来源:发表于2019-12-29 16:51 被阅读0次

一、原理

cache_t:结构体,相当于缓存,缓存的是方法, 它要根据自身结构体所容纳的空间大小来决定其所占字节数。(另外,cache_t是结构体,不是结构体指针。Class为结构体指针,所占字节为8)


struct cache_t {

    struct bucket_t *_buckets; // 8
    mask_t _mask;  // 4
    mask_t _occupied; // 4

通过观察bucket_t可以得出缓存的是一些方法

bucket_t结构体.png

cache_t缓存的是一些方法:

struct method_t {
    SEL name;
    const char *types;
    MethodListIMP imp;

通过以下几个步骤可得出新结论:


图片.png
void testInstanceMethod_classToMetaclass(Class pClass){
    
    const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className);
    
    Method method1 = class_getInstanceMethod(pClass, @selector(sayHello));
    Method method2 = class_getInstanceMethod(metaClass, @selector(sayHello));

    Method method3 = class_getInstanceMethod(pClass, @selector(sayHappy));
    Method method4 = class_getInstanceMethod(metaClass, @selector(sayHappy));
    
    NSLog(@"%p-%p-%p-%p",method1,method2,method3,method4);
    NSLog(@"%s",__func__);
}

void testClassMethod_classToMetaclass(Class pClass){
    
    const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className);
    
    Method method1 = class_getClassMethod(pClass, @selector(sayHello));
    Method method2 = class_getClassMethod(metaClass, @selector(sayHello));

    Method method3 = class_getClassMethod(pClass, @selector(sayHappy));
    Method method4 = class_getClassMethod(metaClass, @selector(sayHappy)); // ?
    
    NSLog(@"%p-%p-%p-%p",method1,method2,method3,method4);
    NSLog(@"%s",__func__);
}

跟进 class_getClassMethod

Method class_getClassMethod(Class cls, SEL sel)
{
    if (!cls  ||  !sel) return nil;

    return class_getInstanceMethod(cls->getMeta(), sel);
}

继续进 cls->getMeta()

   // NOT identical to this->ISA when this is a metaclass
    Class getMeta() {
        if (isMetaClass()) return (Class)this;
        else return this->ISA();
    }

结论:类方法的底层还是实例方法

二、cache_t分析产生的问题:

通过跑码分析打印_buckets的值,得出cache_t常用来缓存第一次的数据,如果一次输出没有值,则可二次或者多次打印。


图片.png

此时有缓存,而且_buckets还有返回值

三、cache_t的缓存流程

mask_t mask();


图片.png

capacity() 其值为1或0,此时还是不知道缓存哪个方法

探究:到底是缓存在哪个方法

——>capacity()——>


图片.png

此时要继续在当前页探究查找关于capacity()的调用情况——>expand() 由此衍生出了扩容类,看源码走向可以得出oldCapacity和newCapacity,如果oldCapacity没有,则*2扩容两倍作为新的INIT_CACHE_SIZE


图片.png
继续跟进INIT_CACHE_SIZE,此时看源码1左移两位100=>4,结果应该为4,但是此时的打印结果_occupied的值还是1,而_mask的值却是3,这是为什么呢?
图片.png

探究:从何时进行扩容

图片.png

跟进void cache_t::expand()中的INIT_CACHE_SIZE

enum {
    INIT_CACHE_SIZE_LOG2 = 2,
    INIT_CACHE_SIZE      = (1 << INIT_CACHE_SIZE_LOG2)
};

继续在当前页查找expand(),直到找到cache_fill_nolock会发现,此时的expand()是在591行的时候被调用的(调起了方法扩容)


图片.png

源码流程分析:
570行:cache_fill_nolock:从缓存入口进入
579行:cache_getImp:再从缓存中得到Imp,判断是否有缓存,缓存中如果拿到,则直接返回
581:cache_t *cache = getCache(cls) :如果没有拿到,要从getCache获取原来的结构体cls
582:cache_key_t key = getKey(sel) :如果没有拿到,要从 getKey获取sel

cache_key_t getKey(SEL sel) 
{
    assert(sel);
    return (cache_key_t)sel;
}

585:occupied():读取开辟占用

587:if (cache->isConstantEmptyCache()):
继续分析三大中情况:
1.cache->reallocate
2.bucket_t bucket = cache->find(key, receiver);
3.bucket->set(key, imp);
591:else if (newOccupied <= capacity / 4 * 3) :正常添加bucket
594:cache->expand():如果以上两种都不是,则
扩容*

图片.png

1.oldCapacity*2 :扩容2倍
2.reallocate(oldCapacity, newCapacity);
3.cache_collect(false); 清理内存


图片.png

整体处理流程大致如下图所示:


图片.png 图片.png

自我感觉有点糙,还可以再细化,后面有机会,我会给大家添加上一个关于缓存的流程分析图会更加直观和清晰~

相关文章

  • 七、cache_t 分析

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

  • cache_t分析

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

  • 类(三)-- cache_t分析

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

  • objc_class中的cache_t分析

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

  • 探索Cache_t

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

  • cache_t结构探一探

    接上文类的结构分析 一.cache_t结构 1.cache_t结构 cache是cache_t类型,那么cache...

  • objc_msgSend消息流程之快速查找

    在上一篇文章中我们分析cache_t的写入流程,有写入那么就会有读取,这篇文章分析cache_t的读取流程 什么是...

  • iOS底层原理 08 : cache_t的分析

    (一)cache_t的结构分析 我们首先来看cache_t的定义: bucket_t的结构 在结构体cache_t...

  • iOS底层之cache_t探索

    前言 这篇文章主要是分析cache_t流程。通过源码探索下类的cache_t主要缓存了哪些信息,又是怎么缓存的。分...

  • cache_t的探究

    前言 今天我们要探究的cache_t在之前的类的结构分析中看到过,在objc_class中存在一个cache_t类...

网友评论

      本文标题:cache_t分析

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