跳到主要内容

方法缓存

问题​

ObjC 的方法缓存是如何工作的?

答案​

cache_t 结构​

struct cache_t {
struct bucket_t *_buckets; // 散列表
mask_t _mask; // 容量 - 1(用于 & 运算)
uint16_t _occupied; // 已使用数量
};

struct bucket_t {
SEL _sel; // 方法名
IMP _imp; // 函数指针
};

查找过程​

缓存扩容​

  • 初始容量 4
  • 使用率超过 3/4 时扩容为 2 倍
  • 扩容时清空旧缓存(而非迁移)
为什么扩容时清空?

因为缓存基于开放寻址法,扩容后 mask 变化,hash 结果不同,旧数据位置不再正确。且方法会在后续调用时重新缓存(局部性原理)。


常见面试问题​

Q1: 为什么用散列表而不是数组?​

答案:散列表查找时间复杂度 O(1)O(1),而数组遍历是 O(n)O(n)。objc_msgSend 是所有方法调用的入口,频率极高,必须保持极致性能。

Q2: objc_msgSend 为什么用汇编实现?​

答案:objc_msgSend 是调用频率最高的函数。汇编可以精确控制寄存器、避免函数调用开销、尾调用优化,比 C 编译结果更快。

相关链接​