本文主要内容

1.通过源码分析cache的缓存内容
2.cache扩容的引出
3.cache_t解析
4.cache扩容规则解析
5.真机测试cache缓存规则

本节内容较难理解,请大家仔细阅读结合源码多看几遍,认真理解!

测试抑郁症、通过源码分析cache的缓存内容

类对象的objc_class结构体中包括ISAsuperclasscachebits这几个成员,在前几篇文章中,我们对ISA有了一定的了解,也研究了包含实例方法、属性、协议等内容bit架构图怎么画s成员,下面我们来研究该结构体中的另一个成员:cache
查看objc4-838.1架构图源码,如果熟读前面的文章,我们测试工程师很容易知道,类对象的内存地ios是什么意思址向右平移16个字节即可得到cache的地址

iOS底层原理之cache底层详解

找到cache的内存地址,通过强转为cache_t类型并读取cache的数据内容。

iOS底层原理之cache底层详解
找到cache_t的源码发现打印的内容即为其结构体的成员。但仍然无法了解这些成员的含义。根据前面的经验,我们去分析cache_t提供的方法。

iOS底层原理之cache底层详解
经过查看cache_t提供的方法,找到一个叫作insert的函数。在insert方法中注意到bucket_t *b = buckets()源码交易平台bucket_t存储的内容就是方法名和方法的实现。接着是对对象b进行set操作,操作对象b时使用数组的格式b[i]调用,所以要分析i如何取值架构图怎么制作

iOS底层原理之cache底层详解

iOS底层原理之cache底层详解

现在开始分析i的取值,首先计算mask_t m = capacity - 1;,已知_maybeMask = bu测试抑郁症的20道题cket_t长度-1(后源码交易平台续详述),所以capacity = oldCapacity =capacity() = mask()数组初始化+1 =_maybeMask+1=buc测试抑郁症ket_t长度-1+1= bucket_t,所以m的值为bucket_t-1

iOS底层原理之cache底层详解

iOS底层原理之cache底层详解

iOS底层原理之cache底层详解

接着测试抑郁程度的问卷计算mask_t begin = cache_hash(sel, m);cache_源码hash算法函数中,先把sel转换成uintptr_t数组指针类型即unsigned long源码交易平台类型的值value(该数字很大)。因此value&mask的结果最大值是mask。所以begin的值最大值就是mbucket_t-1

iOS底层原理之cache底层详解

由此得出i的值不会超过bucket_t-1

验证把"sel"转换成uintptr_t类型即unsigned long类型的数字value很大!

iOS底层原理之cache底层详解

上述的set操作实际上就是对方法的存储。为什么说对对象b进行set操作实际上就是对方法的保存?在set方法中,分别调用了_imp_store和_sel_store函数。

iOS底层原理之cache底层详解

为什么会找到insert的方法?首先cache表示缓存,所以肯定会涉及到插入、删除等操作,这样就顺其自然的关注到这个方法.各位读者经过长期跟随作者的底层源码分析,也会逐渐形成这样的举一反三的思维能力!

总结整个过程:通过buckets()获取到bucket_t *类型的架构图模板b,确定b的取值范围i最大为bucket架构师和程序员的区别_t长度-1,判断通过哈希算法得到的i对应的数组去重方法b[i]的sel是否有值,如果没有值测试仪,通过set函数将imp和sel存入b[i]中;如果b[i]的sel是否等于当前要存储的sel,如果相同说明已经缓存,直接返回;如果b[i]的sel有值并且不等于当前要存储的sel则调用 cache_next函数,当前要存储的ios是什么意思sel存储到下标为i+1的对象中。

由此得出结论:cache是用来缓存方法的,即sel和imp!

二、cache扩容的引出

既然cache是用来缓存方法的,那么cache把方法存储在什么地方呢? 直接读取cache中的成员发现,方法sel和imp并无法获取到。

iOS底层原理之cache底层详解

根据经验会想到去找函数测试抑郁程度的问卷来获取。由一、通过源码分析cache的缓存内容中发现,存储方法selimp的是一个bucket_t的结构体类型。在源码中找到返回bucket_t类型数据的buckets()函数,调用该函数并读取源码之家返回的内存内容,发现确实是存储了selimp,首先存储有class方法。

iOS底层原理之cache底层详解

iOS底层原理之cache底层详解
继续读取,发现存储了respondsToSelector:方法。

iOS底层原理之cache底层详解

三.cache_t解析

cache_t结构体中包含_bucketsAndMaybeM架构师和程序员的区别ask(保证对数据增删改查时线程安全)占用8字节,还有1个联合体,其中包含4个成员:mask_t类型即unsigned int_maybeMask占用4个字节、uint16_数组排序t类型即uios越狱nsigned short类型的_flags占用2个字节、uint16_t类型即unsigned short类型测试工程师_occupied占用2个字节、preo架构图怎么制作pt_cache_t *(指针)类型的_originalPreoptCache占用8个字数组和链表的区别节,所以cache_t结构体总共为16字节!所以源码交易平台,可以验证通过类对象内存平移16个字节即可找到cache得内存地址

iOS底层原理之cache底层详解

四.cache扩容规则解析

二、cache扩容的引出中分析方法的存储时,调用方法method1后,可能只会找到方法class和方法respon架构图模板dsToSelector的存储而找不到metho源码网站d1。这是因为cache进行了扩容。 进入之前研究的insert函数中,在存储方法的s测试抑郁程度的问卷elimp之前,即bucket_t *b = bu源码交易平台ckets();之前实现了cache扩容的数组排序逻辑。

iOS底层原理之cache底层详解

mask_t newOccupied = occupied() + 1;开始分析,occupiedios模拟器()返回cache_t的成员变量_occupied,当第一次进入insert函数时ios应用商店_occupied为0也就是occupied()为0,所以newOccupied值为1;oldCapacity等于bucket_t的长度。

首次调用数组去重方法会进入第测试英文一个ifif (slowpath(ios系统isConsta源码编辑器ntEmptyCache()))),如图中1: INIios是苹果还是安卓T_CACHE_数组和链表的区别SIZEx86_64架构下为1<<2(4),arm64架构下1<<1(2),即capacity在在x8数组指针6_64架构下为4,arm64架构下2,再调用reallocate函数判断是否需测试你适合学心理学吗要释放oldBuckets。即第一次调用insert时,在x86_64架构下开辟一个长度为4的桶子,在arm64架构下开辟一个长度为2的桶子源码时代

如图中2cache_f测试你的自卑程度ill_ratiox86_64架构下为bucket_t长度的3/4,在ar数组去重方法m64架构下为bucket_t长度的7/8。所以如果缓存的大小在x86_64架构下小于等于桶子长度的3/4,在arm64ios14.4.1更新了什么构下小于桶子长度的7/8,在arm64架构下桶子长度小于等于8时不做任何操作。源码编程器

否则,如源码图中3,会进行扩容。释放oldBuckets.

iOS底层原理之cache底层详解

iOS底层原理之cache底层详解

总结:cache扩容规则

  • 在x86_64架构下,当缓存的大小等于桶子长度的3/4的时候,进行两倍扩容;
  • 在arm64架构下,当缓存的大小大于桶子长度的7/8的时候,进行两倍扩容;桶子长度小于等于8时不会扩容。

疑难问题:cache扩容逻辑需要根据源码多次分析理解!

五.真机测试cache缓存规则

数组词过仿写源码中的objc_class结构iOS体,其中也包括仿写ISAsuperclasscachebits这几个成员,利用仿写的objc_class结构体对Class进行转换,这样数组初始化就可以获iOS取到仿测试抑郁症的20道题写的cache中的数据。如下为部分代码供参考:

typedef uint32_t mask_t; // x86_64 & arm64 asm are less efficient
//preopt_cache_entry_t源码模仿
struct lg_preopt_cache_entry_t {
  uint32_t sel_offs;
  uint32_t imp_offs;
};
//preopt_cache_t源码模仿
struct lg_preopt_cache_t {
  int32_t fallback_class_offset;
  union {
    struct {
      uint16_t shift    : 5;
      uint16_t mask    : 11;
    };
    uint16_t hash_params;
  };
  uint16_t occupied  : 14;
  uint16_t has_inlines : 1;
  uint16_t bit_one   : 1;
  struct lg_preopt_cache_entry_t entries;
 
  inline int capacity() const {
    return mask + 1;
  }
};
//bucket_t源码模仿
struct lg_bucket_t {
  IMP _imp;
  SEL _sel;
};
//cache_t源码模仿
struct lg_cache_t {
  uintptr_t _bucketsAndMaybeMask; // 8
  struct lg_preopt_cache_t _originalPreoptCache; // 8
 
  // _bucketsAndMaybeMask is a buckets_t pointer in the low 48 bits
  // _maybeMask is unused, the mask is stored in the top 16 bits.
  // How much the mask is shifted by.
  static constexpr uintptr_t maskShift = 48;
  // Additional bits after the mask which must be zero. msgSend
  // takes advantage of these additional bits to construct the value
  // `mask << 4` from `_maskAndBuckets` in a single instruction.
  static constexpr uintptr_t maskZeroBits = 4;
  // The largest mask value we can store.
  static constexpr uintptr_t maxMask = ((uintptr_t)1 << (64 - maskShift)) - 1;
 
  // The mask applied to `_maskAndBuckets` to retrieve the buckets pointer.
  static constexpr uintptr_t bucketsMask = ((uintptr_t)1 << (maskShift - maskZeroBits)) - 1;
 
  static constexpr uintptr_t preoptBucketsMarker = 1ul;
  // 63..60: hash_mask_shift
  // 59..55: hash_shift
  // 54.. 1: buckets ptr + auth
  //   0: always 1
  static constexpr uintptr_t preoptBucketsMask = 0x007ffffffffffffe;
 
  lg_bucket_t *buckets() {
    return (lg_bucket_t *)(_bucketsAndMaybeMask & bucketsMask);
  }
 
  uint32_t mask() const {
    return _bucketsAndMaybeMask >> maskShift;
  }
 
};
//class_data_bits_t源码模仿
struct lg_class_data_bits_t {
  uintptr_t objc_class;
};
//类源码模仿
struct lg_objc_class {
  Class isa;
  Class superclass;
  struct lg_cache_t cache;
  struct lg_class_data_bits_t bits;
};

如上通过对源码的仿写,对cache扩容规数组排序则进行了验证,即在arm64架构下(iOS为arm64架构)测试抑郁程度的问卷,当缓存的大小大于桶子长度的7/8的时候,进行两倍扩容;桶子长度小于等于8架构图怎么制作时不会扩容!

本文总结

1.cache是用来缓存方法的,缓存源码时代使方法的调用源码中的图片更高效;
2.在x86_64架构测试抑郁症的20道题下,当缓存的大小等于桶测试工程师子长度的3/4的时候,进行两倍扩容;
3.在arm64架构下,当缓存的大小大于桶子长度的7/8的时候,进行两倍扩容;桶子长度小于等于8时不会扩容。

有任架构师证书何问题,欢迎各位评论指出!觉得博主写的还不错的麻烦点个赞喽