文章目录
- iOS - Runtime - Class-方法缓存(cache_t)
- 1. 散列表的存取值
iOS - Runtime - Class-方法缓存(cache_t)
Class内部结构中有个方法缓存(cache_t)
,用散列表(哈希表)
来缓存曾经调用过的方法,可以提高方法的查找速度。(使用空间换时间
的方式来提升速度)
其中,_buckets
就是散列表
,_mask
表示散列表的长度-1
哪一个
类对象
调用的方法,会把该方法缓存到这个类对象
。也就是说,如果class1
调用的方法,最终是在他的父类
或者根类
才找到方法实现,也会把方法混存到class1
,下次class1
再调用此方法,直接在自己
的方法缓存
里面就能找到方法在
当前类
查找,或者当前类没找到继续到父类
或者跟根类
,查找,都是优先
从缓存
里面查找,缓存没找到
再到方法列表
里面去查找
1. 散列表的存取值
0 | NULL |
---|---|
1 | NULL |
2 | bucket_t(_key = @selector(personTest), _imp) |
3 | NULL |
4 | NULL |
5 | NULL |
… | … |
_buckets
就是散列表
,相当于一个数组,有个初始容量
- 存取数据时,假设传入的是
@selector(studentTest)
,使用@selector(studentTest)
这个key& _mask
,得出来的值作为数组的索引值
,使用该索引值存取数据 @selector(studentTest) & _mask <= _mask
,目的是控制
得出来的索引值
在数组最大容量
范围之内
想象一下`&`运算后的值,一定是<= _mask
/**
0b00010101
0b00000001 <- _mask
----------------- & 运算
0b00000001
*/
&_mask
生成的索引值
可能一样
的,怎么解决
,使用索引值
先取一下,判断里面的key
和我们要的key
是否一样,不一样(或者已存在–存值时)直接将索引值-1
,还一样就继续-1
,减到索引值为0
时,把索引值设置为_mask
,继续找,然后再-1
继续找,直到找到想要的key
(或者空位–存值时)- 扩容,按原来空间
2倍
扩容。扩容的时候,会将缓存清掉
,因为_mask
的值已经变了
@oubijiexi