Runtime之方法缓存

作者: o0阿拉斯加的狗0o | 来源:发表于2016-11-15 18:38 被阅读367次

我们都知道,在Objective-c里面,调用一个方法,其实在runtime层的时候会翻译成

     objc_msgSend(receiver, SEL)

可以想象一下,在继承关系中,一个比较深度的子类去调用父类的父类的父类... ...的方法的时候,如果没有缓存,每次都会用isa指针去挨个搜索,查找链是非常长的,如果类中的方法比较多,比较费时费力,可以看一个比较明显的例子:

1.png
在这种情况下,如果没有方法缓存,查找会变得非常耗时。
首先,先看看,方法缓存是放在哪个地方的,在类的定义中就有方法缓存,具体代码如下:
2.png
3.png
4.png
5.png
所以,是方法缓存是根据来的, 并不是根据具体的类的对象来的。

方法缓存的实现可以到runtime源码中去看,为了优化性能,objc_msgSend是用汇编来实现的,在objc-msg-arm.s文件中,具体实现的步骤是:

  1. 判断receiver是否是nil。

  2. 从缓存里面寻找SEL,找到就分发,否则3。

  3. 跳转到 _objc_msgSend_uncached ,利用 _class_lookupMethodAndLoadCache3 方法(objc-class.mm中,具体可以看下面)寻找SEL

对应的代码为:

6.png 7.png

从代码中可以看到, 如果没有找到方法缓存,就会跳转到\_objc\_msg\_uncached这里,里面有\_class\_lookupMethodAndLoadCache3

这个函数的具体的实现如下:

根据注释可以知道:此方法可以避免再去缓存查找方法,直接去方法列表去找。

8.png 9.png

其中:

  1. mask: 表示当前缓存能达到的最大的size,从0开始,所以total = mask + 1

  2. occupied: 表示占用的内存标志,顺便说一句,方法缓存是通过 “散列表” 的形式 实现的,散列表根据 哈希算法来定位位置,所以会产生空位,occupied用来表示已经使用的内存的个数

  3. buckets:就是用数组来表示存储缓存的散列表的存储空间,其中的每一个Method类型表示一个可用的方法缓存。

    注意:其中结构体中,最后一个成员用[1], 说明中这是一个“可变数组”,在我以前接触到的c语言中,发现有的平台是用[0]来表示,有的是用[1]来表示可变数组

具体到Method的定义:

10.png 11.png
  1. name: 表示被缓存的方法名字

  2. types: 存储着方法的的参数类型和返回值类型

  3. imp: 就是方法的具体实现

还有,往散列表中 存方法缓存取方法缓存

  1. 存方法缓存是在objc-cache-old.mm文件中实现的,
    12.png
13.png

这里就是往散列表中存储的具体实现,其中的散列查找算法是:

14.png

位置是通过sel指针偏移后和mask与后的结果得出

  1. 从缓存中取方法
    取缓存的代码是 跟objc_msgSend的实现在同一个文件中,obj-msg-arm.s中,为了查找的性能优化,也是通过汇编来实现的,方法名字是 CacheLookup,具体实现是:
15.png 16.png

根据查阅其中的 汇编关键字 以及注释,可以知道,取缓存和加缓存的逻辑差不多,也是根据hash去定位,如果出现冲突,根据解决hash冲突规则,继续hash, 直到找到为止,这里是 ++ 的实现形式

相关文章

  • Runtime之方法缓存

    我们都知道,在Objective-c里面,调用一个方法,其实在runtime层的时候会翻译成 可以想象一下,在继承...

  • Runtime 之 方法缓存

    Runtime 之 消息发送流程解析这一节已经介绍了消息发送的整个流程,过程中涉及到的方法缓存的插入,将在本节进行...

  • #iOS进阶之Runtime----方法---缓存

    iOS进阶之Runtime----方法---缓存 objc_class构成概要: bits里面可以获取到 clas...

  • Runtime:方法缓存

    目录一,objc_class二,class_ro_t和class_rw_t三,method_t四,方法缓存原理五,...

  • iOS 底层 - runtime之方法缓存

    本文源自本人的学习记录整理与理解,其中参考阅读了部分优秀的博客和书籍,尽量以通俗简单的语句转述。引用到的地方如有遗...

  • Runtime 02 - Class(方法信息列表、方法缓存)

    Runtime 02 - Class(方法信息列表、方法缓存) Class 结构图 关于对 objc_class、...

  • 温故而知新-ObjC Runtime 方法缓存

    简介 ObjC Runtime 的消息传递过程中,会使用方法缓存提高效率。 本文主要是记录方法缓存的几个特点: 每...

  • 面试问题总结

    1.runtime的缓存机制是什么?答案:根据runtime类的数据结构。调用某个方法,首先通过isa和super...

  • Runtime主要用处

    深入理解Objective-C Runtime机制 一:消息转发流程和机制 1、实例方法:本类的缓存方法列表->本...

  • iOS 消息转发流程

    runtime方法查找流程及消息转发 方法查找 方法查找的流程:缓存查找-->当前类查找-->父类逐级查找 1.缓...

网友评论

    本文标题:Runtime之方法缓存

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