1. 关联对象存储(AssociationsHashMap)
// 关联对象的哈希表实现
typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap;
typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMap;
class AssociationsManager {
static AssociationsHashMap *_map; // 全局关联对象表
void set(id object, const void *key, id value) {
// 双层 map:对象 -> (key -> value)
AssociationsHashMap::iterator i = _map->find(object);
if (i != _map->end()) {
ObjectAssociationMap &refs = i->second;
refs[key] = ObjcAssociation(value);
}
}
};
// 特点:
// 1. 双层哈希表结构
// 2. 使用 DenseMap 实现
// 3. 支持动态扩容
注意事项:
- 需要考虑内存开销
- 多层查找可能影响性能
- 需要正确管理关联对象的生命周期
2. 引用计数表(RefcountMap)
// SideTable 中的引用计数表
class SideTable {
RefcountMap refcnts; // 存储对象的引用计数
void retain(id obj) {
RefcountMap::iterator it = refcnts.find(obj);
if (it != refcnts.end()) {
it->second += SIDE_TABLE_RC_ONE;
}
}
};
typedef objc::DenseMap<DisguisedPtr<objc_object>, size_t> RefcountMap;
// 特点:
// 1. 使用 DenseMap 实现
// 2. Key 使用伪装指针
// 3. 需要频繁访问和修改
注意事项:
- 需要保证原子性操作
- 性能要求高
- 内存管理要谨慎
3. 弱引用表(weak_table_t)
// 弱引用哈希表
struct weak_table_t {
weak_entry_t *weak_entries; // 哈希数组
size_t num_entries; // 实际条目数
uintptr_t mask; // 容量掩码
uintptr_t max_hash_displacement; // 最大哈希偏移
weak_entry_t *get(id referent) {
// 使用哈希查找
size_t begin = hash_pointer(referent) & mask;
size_t index = begin;
size_t hash_displacement = 0;
while (weak_entries[index].referent != referent) {
index = (index + 1) & mask;
if (index == begin) break;
hash_displacement++;
}
return &weak_entries[index];
}
};
// 特点:
// 1. 开放寻址法处理冲突
// 2. 使用线性探测
// 3. 记录最大偏移量
注意事项:
- 需要控制装载因子,避免性能下降
- 删除元素时需要特殊处理,避免破坏探测链
- 扩容时需要重新哈希所有元素
4. 方法缓存(cache_t)
// 类的方法缓存
struct cache_t {
struct bucket_t *_buckets; // 哈希表
mask_t _mask; // 容量掩码
mask_t _occupied; // 已使用数量
IMP imp(SEL sel) {
// 使用哈希查找方法实现
bucket_t *b = buckets();
mask_t m = mask();
return findMethod(b, m, sel);
}
};
// 特点:
// 1. 采用散列函数直接寻址
// 2. 缓存最近使用的方法
// 3. 固定大小,满了就清空重建
注意事项:
- 缓存满时会清空重建,而不是扩容
- 性能敏感,需要快速查找
- 线程安全问题需要特别注意
5. 性能优化
// 使用 DenseMap 优化内存使用
template <typename T, typename U, typename V>
class DenseMap {
// 1. 开放寻址法处理冲突
pair<iterator, bool> insert(const T& key, const U& value) {
// 查找空位置
unsigned index = findEmptyBucket(key);
// 插入数据
Buckets[index] = make_pair(key, value);
}
// 2. 自动扩容
void grow() {
unsigned NewSize = size() * 2;
rehash(NewSize);
}
};
6. 使用特点
6.1 线程安全
// 访问 map 时加锁保护
spinlock_t& lock = SideTables()[obj].lock;
lock.lock();
// 操作 map
lock.unlock();
6.2 内存管理
// 定期清理
void cleanup() {
// 遍历并清理无效条目
for (iterator it = map.begin(); it != map.end();) {
if (it->second.expired()) {
it = map.erase(it);
} else {
++it;
}
}
}
6.3 哈希优化
// 优化的哈希函数
static inline uint32_t ptr_hash(const void *key) {
uintptr_t k = (uintptr_t)key;
return (uint32_t)(k ^ (k >> 7));
}
主要使用场景总结:
- 关联对象存储
- 引用计数管理
- 弱引用表实现
- 方法缓存
- 性能优化
使用特点:
- 多采用 DenseMap 实现
- 注重性能优化
- 考虑线程安全
- 自动内存管理
- 哈希冲突处理
7. 实现差异
7.1 冲突处理
// 开放寻址法
void insert(Key key, Value value) {
size_t index = hash(key) & mask;
while (table[index] != empty) {
index = (index + 1) & mask; // 线性探测
}
table[index] = value;
}
// 链地址法
void insert(Key key, Value value) {
size_t index = hash(key) & mask;
table[index].push_back(value); // 添加到链表
}
7.2 扩容策略
// weak_table_t 的扩容
void grow() {
// 当使用率超过 3/4 时扩容
if (num_entries >= capacity * 3/4) {
resize(capacity * 2);
}
}
// cache_t 的重建
void rebuild() {
// 缓存满时直接清空重建
clear();
allocate(capacity);
}
7.3 内存管理
// DenseMap 的内存管理
template <typename Key, typename Value>
class DenseMap {
// 使用连续内存
pair<Key, Value> *Buckets;
// 自动扩容
void grow() {
reallocate(NumEntries * 2);
}
};
8. 性能考虑
8.1 查找效率
// 方法缓存优化
IMP cache_t::imp(SEL sel) {
// 使用位运算优化
mask_t index = (mask_t)(uintptr_t)sel & _mask;
return _buckets[index].imp();
}
8.2 空间效率
// weak_table_t 的空间优化
struct weak_entry_t {
union {
struct {
weak_referrer_t *referrers; // 动态数组
};
struct {
weak_referrer_t inline_referrers[WEAK_INLINE_COUNT]; // 内联存储
};
};
};
总结:
- 不同场景选择不同的哈希表实现
- 需要权衡时间和空间效率
- 要考虑线程安全问题
- 注意内存管理和性能优化
- 合理处理哈希冲突
- 选择适当的扩容策略