Runtime学习基础之class结构之散列表(哈希表)

31 篇文章 0 订阅

上次我们学习runtime的isa,这节课我们继续学习runtime的class结构,这个博客我们主要说class的cache_t cache这个散列表(哈希表),主要是为了让我们更深刻的理解调用过程,通过这个博客,你将学习到:

通过Runtime调用对象方法的过程的更深刻的理解

我们以前如果面试官问你,一个对象调用对象方法的过程是什么样的?你可能会回答:instance通过isa找到类对象,然后调用对象方法,如果找不到就通过superclass找到父类寻找instance方法....通过这个博客,你就可以回答散列表的东西,其实中间还有个通过缓存来取方法列表,典型的通过“空间换时间”的理念.

首先我们先回顾一下class对象

class回顾

其实我们知道,类对象和元类对象里面存储的东西是一样的,只是有些可能是nil,什么意思呢?就是比如我们知道类对象里面存储对象方法,其实元类对象里面也有对象方法这个结合,就是集合为空而已,所以我们之前说:我们姑且认为类对象里面存储对象方法,等等,其实元类对象也是类对象,只是一个特殊的类对象而已.因为都是class对应.

我们先看一下苹果的源码上对class是怎么定义的:

今天我们主要讲得就是这个cache_t cache这个东西,

我们先来看下什么是散列表(哈希表)?

由百度百科定义:散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

我理解的就是:传入一个key,根据某个算法直接找到对应的索引值,速度更快更高效,下面我们就来看看它是怎么工作的

我们先看cathe_t里面是怎么定义的,大家可以点进去看一下如下图(我只截部分图,因为比较简单)

苹果源码截图

其他图就不截图了,我直接整理一个结果,大家看着比较方便

就是通过SEL作为key来查找对应IMP来调用,节约了很多时间

比如下面的例子:

一个方法如果被调用多次,而且每次都是循环查找,势必非常的耗时,如果有缓存,直接从缓存中找,效率非高非常多.当然第一次调用肯定是没有,要缓存以后才能有,

那到底是怎么存储bucker_t的呢?它也是&某个mask来存储,我们先来看一个大致的图

它不是按照顺序存的,而是按照&mask值直接找到对应的索引存储,下次再来取的时候也是一样.你看上图也有些是null,这就是牺牲了一些内存空间换取了一些运行效率,也就是以空间换时间的概念.

可能有人有这个疑问每当&mask的时候,会不会出现相同的结果,这个是有的,苹果也是做了处理.

查看缓列表

现在我们来验证一下上面的结果

上面的结果能很好的证明,缓存中的函数就是init和addheight,所以是全部缓存到里面去了.

因为我们之前也说过,其实是传入key来取出这个imp,key呢?就是@selector(对应的方法),也还有很多其他测试方法,这里就不过多说了.

接下来博客我会介绍runtime的-objc_msgSend,来开始具体学习runtime.

如果觉得我写得对您有所帮助,请关注我,我会持续更新😄

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值