iOS - Objective-C 底层实现中的哈希表

1. 关联对象存储(AssociationsHashMap)

objectivec 复制代码
// 关联对象的哈希表实现
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)

objectivec 复制代码
// 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)

objectivec 复制代码
// 弱引用哈希表
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)

objectivec 复制代码
// 类的方法缓存
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. 性能优化

objectivec 复制代码
// 使用 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 线程安全

objectivec 复制代码
// 访问 map 时加锁保护
spinlock_t& lock = SideTables()[obj].lock;
lock.lock();
// 操作 map
lock.unlock();

6.2 内存管理

objectivec 复制代码
// 定期清理
void cleanup() {
    // 遍历并清理无效条目
    for (iterator it = map.begin(); it != map.end();) {
        if (it->second.expired()) {
            it = map.erase(it);
        } else {
            ++it;
        }
    }
}

6.3 哈希优化

objectivec 复制代码
// 优化的哈希函数
static inline uint32_t ptr_hash(const void *key) {
    uintptr_t k = (uintptr_t)key;
    return (uint32_t)(k ^ (k >> 7));
}

主要使用场景总结:

  1. 关联对象存储
  2. 引用计数管理
  3. 弱引用表实现
  4. 方法缓存
  5. 性能优化

使用特点:

  1. 多采用 DenseMap 实现
  2. 注重性能优化
  3. 考虑线程安全
  4. 自动内存管理
  5. 哈希冲突处理

7. 实现差异

7.1 冲突处理

objectivec 复制代码
// 开放寻址法
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 扩容策略

objectivec 复制代码
// 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 内存管理

objectivec 复制代码
// DenseMap 的内存管理
template <typename Key, typename Value>
class DenseMap {
    // 使用连续内存
    pair<Key, Value> *Buckets;
    
    // 自动扩容
    void grow() {
        reallocate(NumEntries * 2);
    }
};

8. 性能考虑

8.1 查找效率

objectivec 复制代码
// 方法缓存优化
IMP cache_t::imp(SEL sel) {
    // 使用位运算优化
    mask_t index = (mask_t)(uintptr_t)sel & _mask;
    return _buckets[index].imp();
}

8.2 空间效率

objectivec 复制代码
// weak_table_t 的空间优化
struct weak_entry_t {
    union {
        struct {
            weak_referrer_t *referrers;      // 动态数组
        };
        struct {
            weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT]; // 内联存储
        };
    };
};

总结:

  1. 不同场景选择不同的哈希表实现
  2. 需要权衡时间和空间效率
  3. 要考虑线程安全问题
  4. 注意内存管理和性能优化
  5. 合理处理哈希冲突
  6. 选择适当的扩容策略
相关推荐
小林爱2 小时前
【Compose multiplatform教程】05 IOS环境编译
android·前端·ios·kotlin·android studio·多平台
Batac_蝠猫4 小时前
iOS - Objective-C 底层中的内存屏障
ios·objective-c·xcode
_可乐无糖5 小时前
跨平台实践:python中如何检查当前操作系统
android·python·ui·ios·appium·自动化
Techlifehacks5 小时前
[完整指南]如何轻松备份锁定/禁用的iPhone?
ios·cocoa·iphone
Techlifehacks5 小时前
如果 iPhone 丢失或被盗,如何远程擦除 iPhone?
ios·iphone
Batac_蝠猫5 小时前
iOS - block
macos·ios·cocoa
xiaoxiongniunai5 小时前
IOS工程师
科技·ios·objective-c
mosen8685 小时前
Uniapp判断设备是安卓还是 iOS,并调用不同的方法
android·ios·uni-app
Batac_蝠猫6 小时前
iOS - TLS(线程本地存储)
开发语言·ios·objective-c